mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 13:14:07 +08:00
Merge remote-tracking branches 'spi/topic/spidev', 'spi/topic/sunxi', 'spi/topic/ti-qspi', 'spi/topic/topcliff-pch' and 'spi/topic/txx9' into spi-next
This commit is contained in:
commit
1cb2e84873
@ -167,6 +167,11 @@ static void sun4i_spi_set_cs(struct spi_device *spi, bool enable)
|
|||||||
sun4i_spi_write(sspi, SUN4I_CTL_REG, reg);
|
sun4i_spi_write(sspi, SUN4I_CTL_REG, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t sun4i_spi_max_transfer_size(struct spi_device *spi)
|
||||||
|
{
|
||||||
|
return SUN4I_FIFO_DEPTH - 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int sun4i_spi_transfer_one(struct spi_master *master,
|
static int sun4i_spi_transfer_one(struct spi_master *master,
|
||||||
struct spi_device *spi,
|
struct spi_device *spi,
|
||||||
struct spi_transfer *tfr)
|
struct spi_transfer *tfr)
|
||||||
@ -402,6 +407,8 @@ static int sun4i_spi_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sspi->master = master;
|
sspi->master = master;
|
||||||
|
master->max_speed_hz = 100 * 1000 * 1000;
|
||||||
|
master->min_speed_hz = 3 * 1000;
|
||||||
master->set_cs = sun4i_spi_set_cs;
|
master->set_cs = sun4i_spi_set_cs;
|
||||||
master->transfer_one = sun4i_spi_transfer_one;
|
master->transfer_one = sun4i_spi_transfer_one;
|
||||||
master->num_chipselect = 4;
|
master->num_chipselect = 4;
|
||||||
@ -409,6 +416,7 @@ static int sun4i_spi_probe(struct platform_device *pdev)
|
|||||||
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||||
master->dev.of_node = pdev->dev.of_node;
|
master->dev.of_node = pdev->dev.of_node;
|
||||||
master->auto_runtime_pm = true;
|
master->auto_runtime_pm = true;
|
||||||
|
master->max_transfer_size = sun4i_spi_max_transfer_size;
|
||||||
|
|
||||||
sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
|
sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
|
||||||
if (IS_ERR(sspi->hclk)) {
|
if (IS_ERR(sspi->hclk)) {
|
||||||
|
@ -153,6 +153,10 @@ static void sun6i_spi_set_cs(struct spi_device *spi, bool enable)
|
|||||||
sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
|
sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t sun6i_spi_max_transfer_size(struct spi_device *spi)
|
||||||
|
{
|
||||||
|
return SUN6I_FIFO_DEPTH - 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int sun6i_spi_transfer_one(struct spi_master *master,
|
static int sun6i_spi_transfer_one(struct spi_master *master,
|
||||||
struct spi_device *spi,
|
struct spi_device *spi,
|
||||||
@ -394,6 +398,8 @@ static int sun6i_spi_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sspi->master = master;
|
sspi->master = master;
|
||||||
|
master->max_speed_hz = 100 * 1000 * 1000;
|
||||||
|
master->min_speed_hz = 3 * 1000;
|
||||||
master->set_cs = sun6i_spi_set_cs;
|
master->set_cs = sun6i_spi_set_cs;
|
||||||
master->transfer_one = sun6i_spi_transfer_one;
|
master->transfer_one = sun6i_spi_transfer_one;
|
||||||
master->num_chipselect = 4;
|
master->num_chipselect = 4;
|
||||||
@ -401,6 +407,7 @@ static int sun6i_spi_probe(struct platform_device *pdev)
|
|||||||
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||||
master->dev.of_node = pdev->dev.of_node;
|
master->dev.of_node = pdev->dev.of_node;
|
||||||
master->auto_runtime_pm = true;
|
master->auto_runtime_pm = true;
|
||||||
|
master->max_transfer_size = sun6i_spi_max_transfer_size;
|
||||||
|
|
||||||
sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
|
sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
|
||||||
if (IS_ERR(sspi->hclk)) {
|
if (IS_ERR(sspi->hclk)) {
|
||||||
|
@ -141,7 +141,7 @@ static int ti_qspi_setup(struct spi_device *spi)
|
|||||||
u32 clk_ctrl_reg, clk_rate, clk_mask;
|
u32 clk_ctrl_reg, clk_rate, clk_mask;
|
||||||
|
|
||||||
if (spi->master->busy) {
|
if (spi->master->busy) {
|
||||||
dev_dbg(qspi->dev, "master busy doing other trasnfers\n");
|
dev_dbg(qspi->dev, "master busy doing other transfers\n");
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,8 +133,6 @@ struct pch_spi_dma_ctrl {
|
|||||||
* @io_remap_addr: The remapped PCI base address
|
* @io_remap_addr: The remapped PCI base address
|
||||||
* @master: Pointer to the SPI master structure
|
* @master: Pointer to the SPI master structure
|
||||||
* @work: Reference to work queue handler
|
* @work: Reference to work queue handler
|
||||||
* @wk: Workqueue for carrying out execution of the
|
|
||||||
* requests
|
|
||||||
* @wait: Wait queue for waking up upon receiving an
|
* @wait: Wait queue for waking up upon receiving an
|
||||||
* interrupt.
|
* interrupt.
|
||||||
* @transfer_complete: Status of SPI Transfer
|
* @transfer_complete: Status of SPI Transfer
|
||||||
@ -169,7 +167,6 @@ struct pch_spi_data {
|
|||||||
unsigned long io_base_addr;
|
unsigned long io_base_addr;
|
||||||
struct spi_master *master;
|
struct spi_master *master;
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
struct workqueue_struct *wk;
|
|
||||||
wait_queue_head_t wait;
|
wait_queue_head_t wait;
|
||||||
u8 transfer_complete;
|
u8 transfer_complete;
|
||||||
u8 bcurrent_msg_processing;
|
u8 bcurrent_msg_processing;
|
||||||
@ -517,8 +514,7 @@ static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
|
|||||||
|
|
||||||
dev_dbg(&pspi->dev, "%s - Invoked list_add_tail\n", __func__);
|
dev_dbg(&pspi->dev, "%s - Invoked list_add_tail\n", __func__);
|
||||||
|
|
||||||
/* schedule work queue to run */
|
schedule_work(&data->work);
|
||||||
queue_work(data->wk, &data->work);
|
|
||||||
dev_dbg(&pspi->dev, "%s - Invoked queue work\n", __func__);
|
dev_dbg(&pspi->dev, "%s - Invoked queue work\n", __func__);
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
@ -674,7 +670,7 @@ static void pch_spi_nomore_transfer(struct pch_spi_data *data)
|
|||||||
*more messages)
|
*more messages)
|
||||||
*/
|
*/
|
||||||
dev_dbg(&data->master->dev, "%s:Invoke queue_work\n", __func__);
|
dev_dbg(&data->master->dev, "%s:Invoke queue_work\n", __func__);
|
||||||
queue_work(data->wk, &data->work);
|
schedule_work(&data->work);
|
||||||
} else if (data->board_dat->suspend_sts ||
|
} else if (data->board_dat->suspend_sts ||
|
||||||
data->status == STATUS_EXITING) {
|
data->status == STATUS_EXITING) {
|
||||||
dev_dbg(&data->master->dev,
|
dev_dbg(&data->master->dev,
|
||||||
@ -1266,14 +1262,7 @@ static void pch_spi_free_resources(struct pch_spi_board_data *board_dat,
|
|||||||
{
|
{
|
||||||
dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
|
dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
|
||||||
|
|
||||||
/* free workqueue */
|
flush_work(&data->work);
|
||||||
if (data->wk != NULL) {
|
|
||||||
destroy_workqueue(data->wk);
|
|
||||||
data->wk = NULL;
|
|
||||||
dev_dbg(&board_dat->pdev->dev,
|
|
||||||
"%s destroy_workqueue invoked successfully\n",
|
|
||||||
__func__);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pch_spi_get_resources(struct pch_spi_board_data *board_dat,
|
static int pch_spi_get_resources(struct pch_spi_board_data *board_dat,
|
||||||
@ -1283,14 +1272,6 @@ static int pch_spi_get_resources(struct pch_spi_board_data *board_dat,
|
|||||||
|
|
||||||
dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
|
dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
|
||||||
|
|
||||||
/* create workqueue */
|
|
||||||
data->wk = create_singlethread_workqueue(KBUILD_MODNAME);
|
|
||||||
if (!data->wk) {
|
|
||||||
dev_err(&board_dat->pdev->dev,
|
|
||||||
"%s create_singlet hread_workqueue failed\n", __func__);
|
|
||||||
retval = -EBUSY;
|
|
||||||
goto err_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reset PCH SPI h/w */
|
/* reset PCH SPI h/w */
|
||||||
pch_spi_reset(data->master);
|
pch_spi_reset(data->master);
|
||||||
@ -1299,7 +1280,6 @@ static int pch_spi_get_resources(struct pch_spi_board_data *board_dat,
|
|||||||
|
|
||||||
dev_dbg(&board_dat->pdev->dev, "%s data->irq_reg_sts=true\n", __func__);
|
dev_dbg(&board_dat->pdev->dev, "%s data->irq_reg_sts=true\n", __func__);
|
||||||
|
|
||||||
err_return:
|
|
||||||
if (retval != 0) {
|
if (retval != 0) {
|
||||||
dev_err(&board_dat->pdev->dev,
|
dev_err(&board_dat->pdev->dev,
|
||||||
"%s FAIL:invoking pch_spi_free_resources\n", __func__);
|
"%s FAIL:invoking pch_spi_free_resources\n", __func__);
|
||||||
|
@ -72,7 +72,6 @@
|
|||||||
|
|
||||||
|
|
||||||
struct txx9spi {
|
struct txx9spi {
|
||||||
struct workqueue_struct *workqueue;
|
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
spinlock_t lock; /* protect 'queue' */
|
spinlock_t lock; /* protect 'queue' */
|
||||||
struct list_head queue;
|
struct list_head queue;
|
||||||
@ -315,7 +314,7 @@ static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m)
|
|||||||
|
|
||||||
spin_lock_irqsave(&c->lock, flags);
|
spin_lock_irqsave(&c->lock, flags);
|
||||||
list_add_tail(&m->queue, &c->queue);
|
list_add_tail(&m->queue, &c->queue);
|
||||||
queue_work(c->workqueue, &c->work);
|
schedule_work(&c->work);
|
||||||
spin_unlock_irqrestore(&c->lock, flags);
|
spin_unlock_irqrestore(&c->lock, flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -374,10 +373,6 @@ static int txx9spi_probe(struct platform_device *dev)
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
c->workqueue = create_singlethread_workqueue(
|
|
||||||
dev_name(master->dev.parent));
|
|
||||||
if (!c->workqueue)
|
|
||||||
goto exit_busy;
|
|
||||||
c->last_chipselect = -1;
|
c->last_chipselect = -1;
|
||||||
|
|
||||||
dev_info(&dev->dev, "at %#llx, irq %d, %dMHz\n",
|
dev_info(&dev->dev, "at %#llx, irq %d, %dMHz\n",
|
||||||
@ -400,8 +395,6 @@ static int txx9spi_probe(struct platform_device *dev)
|
|||||||
exit_busy:
|
exit_busy:
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
exit:
|
exit:
|
||||||
if (c->workqueue)
|
|
||||||
destroy_workqueue(c->workqueue);
|
|
||||||
clk_disable(c->clk);
|
clk_disable(c->clk);
|
||||||
spi_master_put(master);
|
spi_master_put(master);
|
||||||
return ret;
|
return ret;
|
||||||
@ -412,7 +405,7 @@ static int txx9spi_remove(struct platform_device *dev)
|
|||||||
struct spi_master *master = platform_get_drvdata(dev);
|
struct spi_master *master = platform_get_drvdata(dev);
|
||||||
struct txx9spi *c = spi_master_get_devdata(master);
|
struct txx9spi *c = spi_master_get_devdata(master);
|
||||||
|
|
||||||
destroy_workqueue(c->workqueue);
|
flush_work(&c->work);
|
||||||
clk_disable(c->clk);
|
clk_disable(c->clk);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include <linux/compat.h>
|
#include <linux/compat.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/acpi.h>
|
||||||
|
|
||||||
#include <linux/spi/spi.h>
|
#include <linux/spi/spi.h>
|
||||||
#include <linux/spi/spidev.h>
|
#include <linux/spi/spidev.h>
|
||||||
@ -700,6 +701,43 @@ static const struct of_device_id spidev_dt_ids[] = {
|
|||||||
MODULE_DEVICE_TABLE(of, spidev_dt_ids);
|
MODULE_DEVICE_TABLE(of, spidev_dt_ids);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ACPI
|
||||||
|
|
||||||
|
/* Dummy SPI devices not to be used in production systems */
|
||||||
|
#define SPIDEV_ACPI_DUMMY 1
|
||||||
|
|
||||||
|
static const struct acpi_device_id spidev_acpi_ids[] = {
|
||||||
|
/*
|
||||||
|
* The ACPI SPT000* devices are only meant for development and
|
||||||
|
* testing. Systems used in production should have a proper ACPI
|
||||||
|
* description of the connected peripheral and they should also use
|
||||||
|
* a proper driver instead of poking directly to the SPI bus.
|
||||||
|
*/
|
||||||
|
{ "SPT0001", SPIDEV_ACPI_DUMMY },
|
||||||
|
{ "SPT0002", SPIDEV_ACPI_DUMMY },
|
||||||
|
{ "SPT0003", SPIDEV_ACPI_DUMMY },
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(acpi, spidev_acpi_ids);
|
||||||
|
|
||||||
|
static void spidev_probe_acpi(struct spi_device *spi)
|
||||||
|
{
|
||||||
|
const struct acpi_device_id *id;
|
||||||
|
|
||||||
|
if (!has_acpi_companion(&spi->dev))
|
||||||
|
return;
|
||||||
|
|
||||||
|
id = acpi_match_device(spidev_acpi_ids, &spi->dev);
|
||||||
|
if (WARN_ON(!id))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (id->driver_data == SPIDEV_ACPI_DUMMY)
|
||||||
|
dev_warn(&spi->dev, "do not use this driver in production systems!\n");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline void spidev_probe_acpi(struct spi_device *spi) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static int spidev_probe(struct spi_device *spi)
|
static int spidev_probe(struct spi_device *spi)
|
||||||
@ -719,6 +757,8 @@ static int spidev_probe(struct spi_device *spi)
|
|||||||
!of_match_device(spidev_dt_ids, &spi->dev));
|
!of_match_device(spidev_dt_ids, &spi->dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spidev_probe_acpi(spi);
|
||||||
|
|
||||||
/* Allocate driver data */
|
/* Allocate driver data */
|
||||||
spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);
|
spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);
|
||||||
if (!spidev)
|
if (!spidev)
|
||||||
@ -789,6 +829,7 @@ static struct spi_driver spidev_spi_driver = {
|
|||||||
.driver = {
|
.driver = {
|
||||||
.name = "spidev",
|
.name = "spidev",
|
||||||
.of_match_table = of_match_ptr(spidev_dt_ids),
|
.of_match_table = of_match_ptr(spidev_dt_ids),
|
||||||
|
.acpi_match_table = ACPI_PTR(spidev_acpi_ids),
|
||||||
},
|
},
|
||||||
.probe = spidev_probe,
|
.probe = spidev_probe,
|
||||||
.remove = spidev_remove,
|
.remove = spidev_remove,
|
||||||
|
Loading…
Reference in New Issue
Block a user