summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/spi/samsung,spi.yaml1
-rw-r--r--drivers/spi/spi-dw-core.c5
-rw-r--r--drivers/spi/spi-dw-dma.c25
-rw-r--r--drivers/spi/spi-mpc52xx-psc.c116
-rw-r--r--drivers/spi/spi-s3c64xx.c29
-rw-r--r--drivers/spi/spi-sh.c94
-rw-r--r--drivers/spi/spi-synquacer.c1
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;
}