diff options
-rw-r--r-- | Documentation/devicetree/bindings/spi/samsung,spi.yaml | 1 | ||||
-rw-r--r-- | drivers/spi/spi-dw-core.c | 5 | ||||
-rw-r--r-- | drivers/spi/spi-dw-dma.c | 25 | ||||
-rw-r--r-- | drivers/spi/spi-mpc52xx-psc.c | 116 | ||||
-rw-r--r-- | drivers/spi/spi-s3c64xx.c | 29 | ||||
-rw-r--r-- | drivers/spi/spi-sh.c | 94 | ||||
-rw-r--r-- | drivers/spi/spi-synquacer.c | 1 |
7 files changed, 106 insertions, 165 deletions
diff --git a/Documentation/devicetree/bindings/spi/samsung,spi.yaml b/Documentation/devicetree/bindings/spi/samsung,spi.yaml index a50f24f9359d..ef59ff62e88d 100644 --- a/Documentation/devicetree/bindings/spi/samsung,spi.yaml +++ b/Documentation/devicetree/bindings/spi/samsung,spi.yaml @@ -20,6 +20,7 @@ properties: - samsung,s3c2443-spi # for S3C2443, S3C2416 and S3C2450 - samsung,s3c6410-spi - samsung,s5pv210-spi # for S5PV210 and S5PC110 + - samsung,exynos4210-spi - samsung,exynos5433-spi - tesla,fsd-spi - const: samsung,exynos7-spi diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c index ecea471ff42c..911ea9bddbee 100644 --- a/drivers/spi/spi-dw-core.c +++ b/drivers/spi/spi-dw-core.c @@ -942,7 +942,9 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) if (dws->dma_ops && dws->dma_ops->dma_init) { ret = dws->dma_ops->dma_init(dev, dws); - if (ret) { + if (ret == -EPROBE_DEFER) { + goto err_free_irq; + } else if (ret) { dev_warn(dev, "DMA init failed\n"); } else { master->can_dma = dws->dma_ops->can_dma; @@ -963,6 +965,7 @@ err_dma_exit: if (dws->dma_ops && dws->dma_ops->dma_exit) dws->dma_ops->dma_exit(dws); dw_spi_enable_chip(dws, 0); +err_free_irq: free_irq(dws->irq, master); err_free_master: spi_controller_put(master); diff --git a/drivers/spi/spi-dw-dma.c b/drivers/spi/spi-dw-dma.c index 63e5260100ec..1322b8cce5b7 100644 --- a/drivers/spi/spi-dw-dma.c +++ b/drivers/spi/spi-dw-dma.c @@ -139,15 +139,20 @@ err_exit: static int dw_spi_dma_init_generic(struct device *dev, struct dw_spi *dws) { - dws->rxchan = dma_request_slave_channel(dev, "rx"); - if (!dws->rxchan) - return -ENODEV; + int ret; - dws->txchan = dma_request_slave_channel(dev, "tx"); - if (!dws->txchan) { - dma_release_channel(dws->rxchan); + dws->rxchan = dma_request_chan(dev, "rx"); + if (IS_ERR(dws->rxchan)) { + ret = PTR_ERR(dws->rxchan); dws->rxchan = NULL; - return -ENODEV; + goto err_exit; + } + + dws->txchan = dma_request_chan(dev, "tx"); + if (IS_ERR(dws->txchan)) { + ret = PTR_ERR(dws->txchan); + dws->txchan = NULL; + goto free_rxchan; } dws->master->dma_rx = dws->rxchan; @@ -160,6 +165,12 @@ static int dw_spi_dma_init_generic(struct device *dev, struct dw_spi *dws) dw_spi_dma_sg_burst_init(dws); return 0; + +free_rxchan: + dma_release_channel(dws->rxchan); + dws->rxchan = NULL; +err_exit: + return ret; } static void dw_spi_dma_exit(struct dw_spi *dws) diff --git a/drivers/spi/spi-mpc52xx-psc.c b/drivers/spi/spi-mpc52xx-psc.c index 7654736c2c0e..609311231e64 100644 --- a/drivers/spi/spi-mpc52xx-psc.c +++ b/drivers/spi/spi-mpc52xx-psc.c @@ -37,12 +37,6 @@ struct mpc52xx_psc_spi { struct mpc52xx_psc_fifo __iomem *fifo; unsigned int irq; u8 bits_per_word; - u8 busy; - - struct work_struct work; - - struct list_head queue; - spinlock_t lock; struct completion done; }; @@ -198,69 +192,53 @@ static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi, return 0; } -static void mpc52xx_psc_spi_work(struct work_struct *work) +int mpc52xx_psc_spi_transfer_one_message(struct spi_controller *ctlr, + struct spi_message *m) { - struct mpc52xx_psc_spi *mps = - container_of(work, struct mpc52xx_psc_spi, work); - - spin_lock_irq(&mps->lock); - mps->busy = 1; - while (!list_empty(&mps->queue)) { - struct spi_message *m; - struct spi_device *spi; - struct spi_transfer *t = NULL; - unsigned cs_change; - int status; - - m = container_of(mps->queue.next, struct spi_message, queue); - list_del_init(&m->queue); - spin_unlock_irq(&mps->lock); - - spi = m->spi; - cs_change = 1; - status = 0; - list_for_each_entry (t, &m->transfers, transfer_list) { - if (t->bits_per_word || t->speed_hz) { - status = mpc52xx_psc_spi_transfer_setup(spi, t); - if (status < 0) - break; - } - - if (cs_change) - mpc52xx_psc_spi_activate_cs(spi); - cs_change = t->cs_change; - - status = mpc52xx_psc_spi_transfer_rxtx(spi, t); - if (status) + struct spi_device *spi; + struct spi_transfer *t = NULL; + unsigned cs_change; + int status; + + spi = m->spi; + cs_change = 1; + status = 0; + list_for_each_entry (t, &m->transfers, transfer_list) { + if (t->bits_per_word || t->speed_hz) { + status = mpc52xx_psc_spi_transfer_setup(spi, t); + if (status < 0) break; - m->actual_length += t->len; + } - spi_transfer_delay_exec(t); + if (cs_change) + mpc52xx_psc_spi_activate_cs(spi); + cs_change = t->cs_change; - if (cs_change) - mpc52xx_psc_spi_deactivate_cs(spi); - } + status = mpc52xx_psc_spi_transfer_rxtx(spi, t); + if (status) + break; + m->actual_length += t->len; - m->status = status; - if (m->complete) - m->complete(m->context); + spi_transfer_delay_exec(t); - if (status || !cs_change) + if (cs_change) mpc52xx_psc_spi_deactivate_cs(spi); + } - mpc52xx_psc_spi_transfer_setup(spi, NULL); + m->status = status; + if (status || !cs_change) + mpc52xx_psc_spi_deactivate_cs(spi); - spin_lock_irq(&mps->lock); - } - mps->busy = 0; - spin_unlock_irq(&mps->lock); + mpc52xx_psc_spi_transfer_setup(spi, NULL); + + spi_finalize_current_message(ctlr); + + return 0; } static int mpc52xx_psc_spi_setup(struct spi_device *spi) { - struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); struct mpc52xx_psc_spi_cs *cs = spi->controller_state; - unsigned long flags; if (spi->bits_per_word%8) return -EINVAL; @@ -275,28 +253,6 @@ static int mpc52xx_psc_spi_setup(struct spi_device *spi) cs->bits_per_word = spi->bits_per_word; cs->speed_hz = spi->max_speed_hz; - spin_lock_irqsave(&mps->lock, flags); - if (!mps->busy) - mpc52xx_psc_spi_deactivate_cs(spi); - spin_unlock_irqrestore(&mps->lock, flags); - - return 0; -} - -static int mpc52xx_psc_spi_transfer(struct spi_device *spi, - struct spi_message *m) -{ - struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); - unsigned long flags; - - m->actual_length = 0; - m->status = -EINPROGRESS; - - spin_lock_irqsave(&mps->lock, flags); - list_add_tail(&m->queue, &mps->queue); - schedule_work(&mps->work); - spin_unlock_irqrestore(&mps->lock, flags); - return 0; } @@ -391,7 +347,7 @@ static int mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr, master->num_chipselect = pdata->max_chipselect; } master->setup = mpc52xx_psc_spi_setup; - master->transfer = mpc52xx_psc_spi_transfer; + master->transfer_one_message = mpc52xx_psc_spi_transfer_one_message; master->cleanup = mpc52xx_psc_spi_cleanup; master->dev.of_node = dev->of_node; @@ -415,10 +371,7 @@ static int mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr, goto free_irq; } - spin_lock_init(&mps->lock); init_completion(&mps->done); - INIT_WORK(&mps->work, mpc52xx_psc_spi_work); - INIT_LIST_HEAD(&mps->queue); ret = spi_register_master(master); if (ret < 0) @@ -470,7 +423,6 @@ static int mpc52xx_psc_spi_of_remove(struct platform_device *op) struct spi_master *master = spi_master_get(platform_get_drvdata(op)); struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master); - flush_work(&mps->work); spi_unregister_master(master); free_irq(mps->irq, mps); if (mps->psc) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 819b660dae82..302c1d4a28b1 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -373,6 +373,24 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi) return 0; } +static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi) +{ + struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi); + + if (is_polling(sdd)) + return 0; + + /* Releases DMA channels if they are allocated */ + if (sdd->rx_dma.ch && sdd->tx_dma.ch) { + dma_release_channel(sdd->rx_dma.ch); + dma_release_channel(sdd->tx_dma.ch); + sdd->rx_dma.ch = 0; + sdd->tx_dma.ch = 0; + } + + return 0; +} + static bool s3c64xx_spi_can_dma(struct spi_master *master, struct spi_device *spi, struct spi_transfer *xfer) @@ -804,14 +822,6 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master, xfer->len = origin_len; } - /* Releases DMA channels after data transfer is completed */ - if (sdd->rx_dma.ch && sdd->tx_dma.ch) { - dma_release_channel(sdd->rx_dma.ch); - dma_release_channel(sdd->tx_dma.ch); - sdd->rx_dma.ch = NULL; - sdd->tx_dma.ch = NULL; - } - return status; } @@ -1128,6 +1138,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) master->setup = s3c64xx_spi_setup; master->cleanup = s3c64xx_spi_cleanup; master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; + master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer; master->prepare_message = s3c64xx_spi_prepare_message; master->transfer_one = s3c64xx_spi_transfer_one; master->num_chipselect = sci->num_cs; @@ -1421,7 +1432,7 @@ static const struct s3c64xx_spi_port_config exynos5433_spi_port_config = { .quirks = S3C64XX_SPI_QUIRK_CS_AUTO, }; -static struct s3c64xx_spi_port_config fsd_spi_port_config = { +static const struct s3c64xx_spi_port_config fsd_spi_port_config = { .fifo_lvl_mask = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f}, .rx_lvl_offset = 15, .tx_st_done = 25, diff --git a/drivers/spi/spi-sh.c b/drivers/spi/spi-sh.c index 45f304935332..3e72fad99adf 100644 --- a/drivers/spi/spi-sh.c +++ b/drivers/spi/spi-sh.c @@ -73,11 +73,8 @@ struct spi_sh_data { void __iomem *addr; int irq; struct spi_master *master; - struct list_head queue; - struct work_struct ws; unsigned long cr1; wait_queue_head_t wait; - spinlock_t lock; int width; }; @@ -271,47 +268,39 @@ static int spi_sh_receive(struct spi_sh_data *ss, struct spi_message *mesg, return 0; } -static void spi_sh_work(struct work_struct *work) +static int spi_sh_transfer_one_message(struct spi_controller *ctlr, + struct spi_message *mesg) { - struct spi_sh_data *ss = container_of(work, struct spi_sh_data, ws); - struct spi_message *mesg; + struct spi_sh_data *ss = spi_controller_get_devdata(ctlr); struct spi_transfer *t; - unsigned long flags; int ret; pr_debug("%s: enter\n", __func__); - spin_lock_irqsave(&ss->lock, flags); - while (!list_empty(&ss->queue)) { - mesg = list_entry(ss->queue.next, struct spi_message, queue); - list_del_init(&mesg->queue); - - spin_unlock_irqrestore(&ss->lock, flags); - list_for_each_entry(t, &mesg->transfers, transfer_list) { - pr_debug("tx_buf = %p, rx_buf = %p\n", - t->tx_buf, t->rx_buf); - pr_debug("len = %d, delay.value = %d\n", - t->len, t->delay.value); - - if (t->tx_buf) { - ret = spi_sh_send(ss, mesg, t); - if (ret < 0) - goto error; - } - if (t->rx_buf) { - ret = spi_sh_receive(ss, mesg, t); - if (ret < 0) - goto error; - } - mesg->actual_length += t->len; - } - spin_lock_irqsave(&ss->lock, flags); + spi_sh_clear_bit(ss, SPI_SH_SSA, SPI_SH_CR1); - mesg->status = 0; - if (mesg->complete) - mesg->complete(mesg->context); + list_for_each_entry(t, &mesg->transfers, transfer_list) { + pr_debug("tx_buf = %p, rx_buf = %p\n", + t->tx_buf, t->rx_buf); + pr_debug("len = %d, delay.value = %d\n", + t->len, t->delay.value); + + if (t->tx_buf) { + ret = spi_sh_send(ss, mesg, t); + if (ret < 0) + goto error; + } + if (t->rx_buf) { + ret = spi_sh_receive(ss, mesg, t); + if (ret < 0) + goto error; + } + mesg->actual_length += t->len; } + mesg->status = 0; + spi_finalize_current_message(ctlr); + clear_fifo(ss); spi_sh_set_bit(ss, SPI_SH_SSD, SPI_SH_CR1); udelay(100); @@ -321,12 +310,11 @@ static void spi_sh_work(struct work_struct *work) clear_fifo(ss); - spin_unlock_irqrestore(&ss->lock, flags); - - return; + return 0; error: mesg->status = ret; + spi_finalize_current_message(ctlr); if (mesg->complete) mesg->complete(mesg->context); @@ -334,6 +322,7 @@ static void spi_sh_work(struct work_struct *work) SPI_SH_CR1); clear_fifo(ss); + return ret; } static int spi_sh_setup(struct spi_device *spi) @@ -355,29 +344,6 @@ static int spi_sh_setup(struct spi_device *spi) return 0; } -static int spi_sh_transfer(struct spi_device *spi, struct spi_message *mesg) -{ - struct spi_sh_data *ss = spi_master_get_devdata(spi->master); - unsigned long flags; - - pr_debug("%s: enter\n", __func__); - pr_debug("\tmode = %02x\n", spi->mode); - - spin_lock_irqsave(&ss->lock, flags); - - mesg->actual_length = 0; - mesg->status = -EINPROGRESS; - - spi_sh_clear_bit(ss, SPI_SH_SSA, SPI_SH_CR1); - - list_add_tail(&mesg->queue, &ss->queue); - schedule_work(&ss->ws); - - spin_unlock_irqrestore(&ss->lock, flags); - - return 0; -} - static void spi_sh_cleanup(struct spi_device *spi) { struct spi_sh_data *ss = spi_master_get_devdata(spi->master); @@ -416,7 +382,6 @@ static int spi_sh_remove(struct platform_device *pdev) struct spi_sh_data *ss = platform_get_drvdata(pdev); spi_unregister_master(ss->master); - flush_work(&ss->ws); free_irq(ss->irq, ss); return 0; @@ -467,9 +432,6 @@ static int spi_sh_probe(struct platform_device *pdev) dev_err(&pdev->dev, "ioremap error.\n"); return -ENOMEM; } - INIT_LIST_HEAD(&ss->queue); - spin_lock_init(&ss->lock); - INIT_WORK(&ss->ws, spi_sh_work); init_waitqueue_head(&ss->wait); ret = request_irq(irq, spi_sh_irq, 0, "spi_sh", ss); @@ -481,7 +443,7 @@ static int spi_sh_probe(struct platform_device *pdev) master->num_chipselect = 2; master->bus_num = pdev->id; master->setup = spi_sh_setup; - master->transfer = spi_sh_transfer; + master->transfer_one_message = spi_sh_transfer_one_message; master->cleanup = spi_sh_cleanup; ret = spi_register_master(master); diff --git a/drivers/spi/spi-synquacer.c b/drivers/spi/spi-synquacer.c index ea706d9629cb..47cbe73137c2 100644 --- a/drivers/spi/spi-synquacer.c +++ b/drivers/spi/spi-synquacer.c @@ -783,6 +783,7 @@ static int __maybe_unused synquacer_spi_resume(struct device *dev) ret = synquacer_spi_enable(master); if (ret) { + clk_disable_unprepare(sspi->clk); dev_err(dev, "failed to enable spi (%d)\n", ret); return ret; } |