aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/Kconfig4
-rw-r--r--drivers/spi/atmel-quadspi.c42
-rw-r--r--drivers/spi/spi-amd.c5
-rw-r--r--drivers/spi/spi-ar934x.c14
-rw-r--r--drivers/spi/spi-atmel.c6
-rw-r--r--drivers/spi/spi-bcm-qspi.c34
-rw-r--r--drivers/spi/spi-bcm2835.c24
-rw-r--r--drivers/spi/spi-bcm2835aux.c20
-rw-r--r--drivers/spi/spi-bcm63xx-hsspi.c4
-rw-r--r--drivers/spi/spi-cadence-quadspi.c2
-rw-r--r--drivers/spi/spi-davinci.c2
-rw-r--r--drivers/spi/spi-dw-bt1.c6
-rw-r--r--drivers/spi/spi-dw-core.c51
-rw-r--r--drivers/spi/spi-dw-mmio.c16
-rw-r--r--drivers/spi/spi-dw.h5
-rw-r--r--drivers/spi/spi-fsi.c2
-rw-r--r--drivers/spi/spi-fsl-dspi.c6
-rw-r--r--drivers/spi/spi-fsl-lpspi.c3
-rw-r--r--drivers/spi/spi-fsl-spi.c11
-rw-r--r--drivers/spi/spi-geni-qcom.c4
-rw-r--r--drivers/spi/spi-gpio.c15
-rw-r--r--drivers/spi/spi-img-spfi.c4
-rw-r--r--drivers/spi/spi-imx.c34
-rw-r--r--drivers/spi/spi-mem.c3
-rw-r--r--drivers/spi/spi-mt7621.c11
-rw-r--r--drivers/spi/spi-mtk-nor.c18
-rw-r--r--drivers/spi/spi-mxic.c10
-rw-r--r--drivers/spi/spi-mxs.c1
-rw-r--r--drivers/spi/spi-npcm-fiu.c10
-rw-r--r--drivers/spi/spi-nxp-fspi.c7
-rw-r--r--drivers/spi/spi-pic32.c1
-rw-r--r--drivers/spi/spi-pxa2xx.c10
-rw-r--r--drivers/spi/spi-qcom-qspi.c42
-rw-r--r--drivers/spi/spi-rb4xx.c2
-rw-r--r--drivers/spi/spi-rockchip.c4
-rw-r--r--drivers/spi/spi-rpc-if.c9
-rw-r--r--drivers/spi/spi-sc18is602.c13
-rw-r--r--drivers/spi/spi-sh.c13
-rw-r--r--drivers/spi/spi-sprd.c1
-rw-r--r--drivers/spi/spi-st-ssc4.c5
-rw-r--r--drivers/spi/spi-stm32-qspi.c8
-rw-r--r--drivers/spi/spi-stm32.c1
-rw-r--r--drivers/spi/spi-sun6i.c199
-rw-r--r--drivers/spi/spi-synquacer.c15
-rw-r--r--drivers/spi/spi-tegra114.c2
-rw-r--r--drivers/spi/spi-tegra20-sflash.c1
-rw-r--r--drivers/spi/spi-tegra20-slink.c2
-rw-r--r--drivers/spi/spi-ti-qspi.c1
-rw-r--r--drivers/spi/spi.c156
49 files changed, 552 insertions, 307 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 5cff60de8e83..aadaea052f51 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -255,6 +255,8 @@ config SPI_DW_MMIO
config SPI_DW_BT1
tristate "Baikal-T1 SPI driver for DW SPI core"
depends on MIPS_BAIKAL_T1 || COMPILE_TEST
+ select MULTIPLEXER
+ select MUX_MMIO
help
Baikal-T1 SoC is equipped with three DW APB SSI-based MMIO SPI
controllers. Two of them are pretty much normal: with IRQ, DMA,
@@ -268,8 +270,6 @@ config SPI_DW_BT1
config SPI_DW_BT1_DIRMAP
bool "Directly mapped Baikal-T1 Boot SPI flash support"
depends on SPI_DW_BT1
- select MULTIPLEXER
- select MUX_MMIO
help
Directly mapped SPI flash memory is an interface specific to the
Baikal-T1 System Boot Controller. It is a 16MB MMIO region, which
diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
index 8c009c175f2c..10bc5390ab91 100644
--- a/drivers/spi/atmel-quadspi.c
+++ b/drivers/spi/atmel-quadspi.c
@@ -365,10 +365,14 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq,
if (dummy_cycles)
ifr |= QSPI_IFR_NBDUM(dummy_cycles);
- /* Set data enable */
- if (op->data.nbytes)
+ /* Set data enable and data transfer type. */
+ if (op->data.nbytes) {
ifr |= QSPI_IFR_DATAEN;
+ if (op->addr.nbytes)
+ ifr |= QSPI_IFR_TFRTYP_MEM;
+ }
+
/*
* If the QSPI controller is set in regular SPI mode, set it in
* Serial Memory Mode (SMM).
@@ -381,27 +385,24 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq,
/* Clear pending interrupts */
(void)atmel_qspi_read(aq, QSPI_SR);
- if (aq->caps->has_ricr) {
- if (!op->addr.nbytes && op->data.dir == SPI_MEM_DATA_IN)
- ifr |= QSPI_IFR_APBTFRTYP_READ;
-
- /* Set QSPI Instruction Frame registers */
+ /* Set QSPI Instruction Frame registers. */
+ if (op->addr.nbytes && !op->data.nbytes)
atmel_qspi_write(iar, aq, QSPI_IAR);
+
+ if (aq->caps->has_ricr) {
if (op->data.dir == SPI_MEM_DATA_IN)
atmel_qspi_write(icr, aq, QSPI_RICR);
else
atmel_qspi_write(icr, aq, QSPI_WICR);
- atmel_qspi_write(ifr, aq, QSPI_IFR);
} else {
- if (op->data.dir == SPI_MEM_DATA_OUT)
+ if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT)
ifr |= QSPI_IFR_SAMA5D2_WRITE_TRSFR;
- /* Set QSPI Instruction Frame registers */
- atmel_qspi_write(iar, aq, QSPI_IAR);
atmel_qspi_write(icr, aq, QSPI_ICR);
- atmel_qspi_write(ifr, aq, QSPI_IFR);
}
+ atmel_qspi_write(ifr, aq, QSPI_IFR);
+
return 0;
}
@@ -535,7 +536,7 @@ static int atmel_qspi_probe(struct platform_device *pdev)
struct resource *res;
int irq, err = 0;
- ctrl = spi_alloc_master(&pdev->dev, sizeof(*aq));
+ ctrl = devm_spi_alloc_master(&pdev->dev, sizeof(*aq));
if (!ctrl)
return -ENOMEM;
@@ -557,8 +558,7 @@ static int atmel_qspi_probe(struct platform_device *pdev)
aq->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(aq->regs)) {
dev_err(&pdev->dev, "missing registers\n");
- err = PTR_ERR(aq->regs);
- goto exit;
+ return PTR_ERR(aq->regs);
}
/* Map the AHB memory */
@@ -566,8 +566,7 @@ static int atmel_qspi_probe(struct platform_device *pdev)
aq->mem = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(aq->mem)) {
dev_err(&pdev->dev, "missing AHB memory\n");
- err = PTR_ERR(aq->mem);
- goto exit;
+ return PTR_ERR(aq->mem);
}
aq->mmap_size = resource_size(res);
@@ -579,22 +578,21 @@ static int atmel_qspi_probe(struct platform_device *pdev)
if (IS_ERR(aq->pclk)) {
dev_err(&pdev->dev, "missing peripheral clock\n");
- err = PTR_ERR(aq->pclk);
- goto exit;
+ return PTR_ERR(aq->pclk);
}
/* Enable the peripheral clock */
err = clk_prepare_enable(aq->pclk);
if (err) {
dev_err(&pdev->dev, "failed to enable the peripheral clock\n");
- goto exit;
+ return err;
}
aq->caps = of_device_get_match_data(&pdev->dev);
if (!aq->caps) {
dev_err(&pdev->dev, "Could not retrieve QSPI caps\n");
err = -EINVAL;
- goto exit;
+ goto disable_pclk;
}
if (aq->caps->has_qspick) {
@@ -638,8 +636,6 @@ disable_qspick:
clk_disable_unprepare(aq->qspick);
disable_pclk:
clk_disable_unprepare(aq->pclk);
-exit:
- spi_controller_put(ctrl);
return err;
}
diff --git a/drivers/spi/spi-amd.c b/drivers/spi/spi-amd.c
index 7f629544060d..3cf76096a76d 100644
--- a/drivers/spi/spi-amd.c
+++ b/drivers/spi/spi-amd.c
@@ -250,7 +250,6 @@ static int amd_spi_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct spi_master *master;
struct amd_spi *amd_spi;
- struct resource *res;
int err = 0;
/* Allocate storage for spi_master and driver private data */
@@ -261,9 +260,7 @@ static int amd_spi_probe(struct platform_device *pdev)
}
amd_spi = spi_master_get_devdata(master);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- amd_spi->io_remap_addr = devm_ioremap_resource(&pdev->dev, res);
+ amd_spi->io_remap_addr = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(amd_spi->io_remap_addr)) {
err = PTR_ERR(amd_spi->io_remap_addr);
dev_err(dev, "error %d ioremap of SPI registers failed\n", err);
diff --git a/drivers/spi/spi-ar934x.c b/drivers/spi/spi-ar934x.c
index d08dec09d423..def32e0aaefe 100644
--- a/drivers/spi/spi-ar934x.c
+++ b/drivers/spi/spi-ar934x.c
@@ -176,10 +176,11 @@ static int ar934x_spi_probe(struct platform_device *pdev)
if (ret)
return ret;
- ctlr = spi_alloc_master(&pdev->dev, sizeof(*sp));
+ ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*sp));
if (!ctlr) {
dev_info(&pdev->dev, "failed to allocate spi controller\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err_clk_disable;
}
/* disable flash mapping and expose spi controller registers */
@@ -202,7 +203,13 @@ static int ar934x_spi_probe(struct platform_device *pdev)
sp->clk_freq = clk_get_rate(clk);
sp->ctlr = ctlr;
- return devm_spi_register_controller(&pdev->dev, ctlr);
+ ret = spi_register_controller(ctlr);
+ if (!ret)
+ return 0;
+
+err_clk_disable:
+ clk_disable_unprepare(clk);
+ return ret;
}
static int ar934x_spi_remove(struct platform_device *pdev)
@@ -213,6 +220,7 @@ static int ar934x_spi_remove(struct platform_device *pdev)
ctlr = dev_get_drvdata(&pdev->dev);
sp = spi_controller_get_devdata(ctlr);
+ spi_unregister_controller(ctlr);
clk_disable_unprepare(sp->clk);
return 0;
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 0e5e64a80848..948396b382d7 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -512,8 +512,8 @@ static int atmel_spi_configure_dma(struct spi_master *master,
master->dma_tx = dma_request_chan(dev, "tx");
if (IS_ERR(master->dma_tx)) {
- err = dev_err_probe(dev, PTR_ERR(master->dma_tx),
- "No TX DMA channel, DMA is disabled\n");
+ err = PTR_ERR(master->dma_tx);
+ dev_dbg(dev, "No TX DMA channel, DMA is disabled\n");
goto error_clear;
}
@@ -524,7 +524,7 @@ static int atmel_spi_configure_dma(struct spi_master *master,
* No reason to check EPROBE_DEFER here since we have already
* requested tx channel.
*/
- dev_err(dev, "No RX DMA channel, DMA is disabled\n");
+ dev_dbg(dev, "No RX DMA channel, DMA is disabled\n");
goto error;
}
diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c
index 14c9d0133bce..c028446c7460 100644
--- a/drivers/spi/spi-bcm-qspi.c
+++ b/drivers/spi/spi-bcm-qspi.c
@@ -1327,7 +1327,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
data = of_id->data;
- master = spi_alloc_master(dev, sizeof(struct bcm_qspi));
+ master = devm_spi_alloc_master(dev, sizeof(struct bcm_qspi));
if (!master) {
dev_err(dev, "error allocating spi_master\n");
return -ENOMEM;
@@ -1367,21 +1367,17 @@ int bcm_qspi_probe(struct platform_device *pdev,
if (res) {
qspi->base[MSPI] = devm_ioremap_resource(dev, res);
- if (IS_ERR(qspi->base[MSPI])) {
- ret = PTR_ERR(qspi->base[MSPI]);
- goto qspi_resource_err;
- }
+ if (IS_ERR(qspi->base[MSPI]))
+ return PTR_ERR(qspi->base[MSPI]);
} else {
- goto qspi_resource_err;
+ return 0;
}
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi");
if (res) {
qspi->base[BSPI] = devm_ioremap_resource(dev, res);
- if (IS_ERR(qspi->base[BSPI])) {
- ret = PTR_ERR(qspi->base[BSPI]);
- goto qspi_resource_err;
- }
+ if (IS_ERR(qspi->base[BSPI]))
+ return PTR_ERR(qspi->base[BSPI]);
qspi->bspi_mode = true;
} else {
qspi->bspi_mode = false;
@@ -1392,18 +1388,14 @@ int bcm_qspi_probe(struct platform_device *pdev,
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cs_reg");
if (res) {
qspi->base[CHIP_SELECT] = devm_ioremap_resource(dev, res);
- if (IS_ERR(qspi->base[CHIP_SELECT])) {
- ret = PTR_ERR(qspi->base[CHIP_SELECT]);
- goto qspi_resource_err;
- }
+ if (IS_ERR(qspi->base[CHIP_SELECT]))
+ return PTR_ERR(qspi->base[CHIP_SELECT]);
}
qspi->dev_ids = kcalloc(num_irqs, sizeof(struct bcm_qspi_dev_id),
GFP_KERNEL);
- if (!qspi->dev_ids) {
- ret = -ENOMEM;
- goto qspi_resource_err;
- }
+ if (!qspi->dev_ids)
+ return -ENOMEM;
for (val = 0; val < num_irqs; val++) {
irq = -1;
@@ -1484,7 +1476,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
qspi->xfer_mode.addrlen = -1;
qspi->xfer_mode.hp = -1;
- ret = devm_spi_register_master(&pdev->dev, master);
+ ret = spi_register_master(master);
if (ret < 0) {
dev_err(dev, "can't register master\n");
goto qspi_reg_err;
@@ -1497,8 +1489,6 @@ qspi_reg_err:
clk_disable_unprepare(qspi->clk);
qspi_probe_err:
kfree(qspi->dev_ids);
-qspi_resource_err:
- spi_master_put(master);
return ret;
}
/* probe function to be called by SoC specific platform driver probe */
@@ -1508,10 +1498,10 @@ int bcm_qspi_remove(struct platform_device *pdev)
{
struct bcm_qspi *qspi = platform_get_drvdata(pdev);
+ spi_unregister_master(qspi->master);
bcm_qspi_hw_uninit(qspi);
clk_disable_unprepare(qspi->clk);
kfree(qspi->dev_ids);
- spi_unregister_master(qspi->master);
return 0;
}
diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
index 7104cf17b848..197485f2c2b2 100644
--- a/drivers/spi/spi-bcm2835.c
+++ b/drivers/spi/spi-bcm2835.c
@@ -1278,7 +1278,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
struct bcm2835_spi *bs;
int err;
- ctlr = spi_alloc_master(&pdev->dev, ALIGN(sizeof(*bs),
+ ctlr = devm_spi_alloc_master(&pdev->dev, ALIGN(sizeof(*bs),
dma_get_cache_alignment()));
if (!ctlr)
return -ENOMEM;
@@ -1299,23 +1299,17 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
bs->ctlr = ctlr;
bs->regs = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(bs->regs)) {
- err = PTR_ERR(bs->regs);
- goto out_controller_put;
- }
+ if (IS_ERR(bs->regs))
+ return PTR_ERR(bs->regs);
bs->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(bs->clk)) {
- err = dev_err_probe(&pdev->dev, PTR_ERR(bs->clk),
- "could not get clk\n");
- goto out_controller_put;
- }
+ if (IS_ERR(bs->clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(bs->clk),
+ "could not get clk\n");
bs->irq = platform_get_irq(pdev, 0);
- if (bs->irq <= 0) {
- err = bs->irq ? bs->irq : -ENODEV;
- goto out_controller_put;
- }
+ if (bs->irq <= 0)
+ return bs->irq ? bs->irq : -ENODEV;
clk_prepare_enable(bs->clk);
@@ -1349,8 +1343,6 @@ out_dma_release:
bcm2835_dma_release(ctlr, bs);
out_clk_disable:
clk_disable_unprepare(bs->clk);
-out_controller_put:
- spi_controller_put(ctlr);
return err;
}
diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c
index 03b034c15d2b..1a26865c42f8 100644
--- a/drivers/spi/spi-bcm2835aux.c
+++ b/drivers/spi/spi-bcm2835aux.c
@@ -494,7 +494,7 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
unsigned long clk_hz;
int err;
- master = spi_alloc_master(&pdev->dev, sizeof(*bs));
+ master = devm_spi_alloc_master(&pdev->dev, sizeof(*bs));
if (!master)
return -ENOMEM;
@@ -524,29 +524,25 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
/* the main area */
bs->regs = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(bs->regs)) {
- err = PTR_ERR(bs->regs);
- goto out_master_put;
- }
+ if (IS_ERR(bs->regs))
+ return PTR_ERR(bs->regs);
bs->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(bs->clk)) {
err = PTR_ERR(bs->clk);
dev_err(&pdev->dev, "could not get clk: %d\n", err);
- goto out_master_put;
+ return err;
}
bs->irq = platform_get_irq(pdev, 0);
- if (bs->irq <= 0) {
- err = bs->irq ? bs->irq : -ENODEV;
- goto out_master_put;
- }
+ if (bs->irq <= 0)
+ return bs->irq ? bs->irq : -ENODEV;
/* this also enables the HW block */
err = clk_prepare_enable(bs->clk);
if (err) {
dev_err(&pdev->dev, "could not prepare clock: %d\n", err);
- goto out_master_put;
+ return err;
}
/* just checking if the clock returns a sane value */
@@ -581,8 +577,6 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
out_clk_disable:
clk_disable_unprepare(bs->clk);
-out_master_put:
- spi_master_put(master);
return err;
}
diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c
index 9909b18f3c5a..1f08d7553f07 100644
--- a/drivers/spi/spi-bcm63xx-hsspi.c
+++ b/drivers/spi/spi-bcm63xx-hsspi.c
@@ -494,8 +494,10 @@ static int bcm63xx_hsspi_resume(struct device *dev)
if (bs->pll_clk) {
ret = clk_prepare_enable(bs->pll_clk);
- if (ret)
+ if (ret) {
+ clk_disable_unprepare(bs->clk);
return ret;
+ }
}
spi_master_resume(master);
diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
index 40938cf3806d..ba7d40c2922f 100644
--- a/drivers/spi/spi-cadence-quadspi.c
+++ b/drivers/spi/spi-cadence-quadspi.c
@@ -1260,12 +1260,14 @@ static int cqspi_probe(struct platform_device *pdev)
/* Obtain QSPI reset control */
rstc = devm_reset_control_get_optional_exclusive(dev, "qspi");
if (IS_ERR(rstc)) {
+ ret = PTR_ERR(rstc);
dev_err(dev, "Cannot get QSPI reset.\n");
goto probe_reset_failed;
}
rstc_ocp = devm_reset_control_get_optional_exclusive(dev, "qspi-ocp");
if (IS_ERR(rstc_ocp)) {
+ ret = PTR_ERR(rstc_ocp);
dev_err(dev, "Cannot get QSPI OCP reset.\n");
goto probe_reset_failed;
}
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index 818f2b22875d..7453a1dbbc06 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -1040,13 +1040,13 @@ static int davinci_spi_remove(struct platform_device *pdev)
spi_bitbang_stop(&dspi->bitbang);
clk_disable_unprepare(dspi->clk);
- spi_master_put(master);
if (dspi->dma_rx) {
dma_release_channel(dspi->dma_rx);
dma_release_channel(dspi->dma_tx);
}
+ spi_master_put(master);
return 0;
}
diff --git a/drivers/spi/spi-dw-bt1.c b/drivers/spi/spi-dw-bt1.c
index f382dfad7842..4aa8596fb1f2 100644
--- a/drivers/spi/spi-dw-bt1.c
+++ b/drivers/spi/spi-dw-bt1.c
@@ -217,7 +217,7 @@ static int dw_spi_bt1_sys_init(struct platform_device *pdev,
if (mem) {
dwsbt1->map = devm_ioremap_resource(&pdev->dev, mem);
if (!IS_ERR(dwsbt1->map)) {
- dwsbt1->map_len = (mem->end - mem->start + 1);
+ dwsbt1->map_len = resource_size(mem);
dws->mem_ops.dirmap_create = dw_spi_bt1_dirmap_create;
dws->mem_ops.dirmap_read = dw_spi_bt1_dirmap_read;
} else {
@@ -280,8 +280,10 @@ static int dw_spi_bt1_probe(struct platform_device *pdev)
dws->bus_num = pdev->id;
dws->reg_io_width = 4;
dws->max_freq = clk_get_rate(dwsbt1->clk);
- if (!dws->max_freq)
+ if (!dws->max_freq) {
+ ret = -EINVAL;
goto err_disable_clk;
+ }
init_func = device_get_match_data(&pdev->dev);
ret = init_func(pdev, dwsbt1);
diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index 2e50cc0a9291..a305074c482e 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -137,14 +137,16 @@ static inline u32 rx_max(struct dw_spi *dws)
static void dw_writer(struct dw_spi *dws)
{
u32 max = tx_max(dws);
- u16 txw = 0;
+ u32 txw = 0;
while (max--) {
if (dws->tx) {
if (dws->n_bytes == 1)
txw = *(u8 *)(dws->tx);
- else
+ else if (dws->n_bytes == 2)
txw = *(u16 *)(dws->tx);
+ else
+ txw = *(u32 *)(dws->tx);
dws->tx += dws->n_bytes;
}
@@ -156,15 +158,17 @@ static void dw_writer(struct dw_spi *dws)
static void dw_reader(struct dw_spi *dws)
{
u32 max = rx_max(dws);
- u16 rxw;
+ u32 rxw;
while (max--) {
rxw = dw_read_io_reg(dws, DW_SPI_DR);
if (dws->rx) {
if (dws->n_bytes == 1)
*(u8 *)(dws->rx) = rxw;
- else
+ else if (dws->n_bytes == 2)
*(u16 *)(dws->rx) = rxw;
+ else
+ *(u32 *)(dws->rx) = rxw;
dws->rx += dws->n_bytes;
}
@@ -311,8 +315,8 @@ void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
u32 speed_hz;
u16 clk_div;
- /* CTRLR0[ 4/3: 0] Data Frame Size */
- cr0 |= (cfg->dfs - 1);
+ /* CTRLR0[ 4/3: 0] or CTRLR0[ 20: 16] Data Frame Size */
+ cr0 |= (cfg->dfs - 1) << dws->dfs_offset;
if (!(dws->caps & DW_SPI_CAP_DWC_SSI))
/* CTRLR0[ 9:8] Transfer Mode */
@@ -357,11 +361,11 @@ static void dw_spi_irq_setup(struct dw_spi *dws)
dw_writel(dws, DW_SPI_TXFTLR, level);
dw_writel(dws, DW_SPI_RXFTLR, level - 1);
+ dws->transfer_handler = dw_spi_transfer_handler;
+
imask = SPI_INT_TXEI | SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI |
SPI_INT_RXFI;
spi_umask_intr(dws, imask);
-
- dws->transfer_handler = dw_spi_transfer_handler;
}
/*
@@ -828,6 +832,29 @@ static void spi_hw_init(struct device *dev, struct dw_spi *dws)
dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len);
}
+ /*
+ * Detect CTRLR0.DFS field size and offset by testing the lowest bits
+ * writability. Note DWC SSI controller also has the extended DFS, but
+ * with zero offset.
+ */
+ if (!(dws->caps & DW_SPI_CAP_DWC_SSI)) {
+ u32 cr0, tmp = dw_readl(dws, DW_SPI_CTRLR0);
+
+ spi_enable_chip(dws, 0);
+ dw_writel(dws, DW_SPI_CTRLR0, 0xffffffff);
+ cr0 = dw_readl(dws, DW_SPI_CTRLR0);
+ dw_writel(dws, DW_SPI_CTRLR0, tmp);
+ spi_enable_chip(dws, 1);
+
+ if (!(cr0 & SPI_DFS_MASK)) {
+ dws->caps |= DW_SPI_CAP_DFS32;
+ dws->dfs_offset = SPI_DFS32_OFFSET;
+ dev_dbg(dev, "Detected 32-bits max data frame size\n");
+ }
+ } else {
+ dws->caps |= DW_SPI_CAP_DFS32;
+ }
+
/* enable HW fixup for explicit CS deselect for Amazon's alpine chip */
if (dws->caps & DW_SPI_CAP_CS_OVERRIDE)
dw_writel(dws, DW_SPI_CS_OVERRIDE, 0xF);
@@ -864,7 +891,10 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
master->use_gpio_descriptors = true;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP;
- master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
+ if (dws->caps & DW_SPI_CAP_DFS32)
+ master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
+ else
+ master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
master->bus_num = dws->bus_num;
master->num_chipselect = dws->num_cs;
master->setup = dw_spi_setup;
@@ -875,7 +905,8 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
master->set_cs = dw_spi_set_cs;
master->transfer_one = dw_spi_transfer_one;
master->handle_err = dw_spi_handle_err;
- master->mem_ops = &dws->mem_ops;
+ if (dws->mem_ops.exec_op)
+ master->mem_ops = &dws->mem_ops;
master->max_speed_hz = dws->max_freq;
master->dev.of_node = dev->of_node;
master->dev.fwnode = dev->fwnode;
diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index d0cc5bf4fa4e..17c06039a74d 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -222,6 +222,21 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
return 0;
}
+static int dw_spi_canaan_k210_init(struct platform_device *pdev,
+ struct dw_spi_mmio *dwsmmio)
+{
+ /*
+ * The Canaan Kendryte K210 SoC DW apb_ssi v4 spi controller is
+ * documented to have a 32 word deep TX and RX FIFO, which
+ * spi_hw_init() detects. However, when the RX FIFO is filled up to
+ * 32 entries (RXFLR = 32), an RX FIFO overrun error occurs. Avoid this
+ * problem by force setting fifo_len to 31.
+ */
+ dwsmmio->dws.fifo_len = 31;
+
+ return 0;
+}
+
static int dw_spi_mmio_probe(struct platform_device *pdev)
{
int (*init_func)(struct platform_device *pdev,
@@ -335,6 +350,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
{ .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
+ { .compatible = "canaan,k210-spi", dw_spi_canaan_k210_init},
{ /* end of table */}
};
MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index faf40cb66498..b665e040862c 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -9,6 +9,7 @@
#include <linux/io.h>
#include <linux/scatterlist.h>
#include <linux/spi/spi-mem.h>
+#include <linux/bitfield.h>
/* Register offsets */
#define DW_SPI_CTRLR0 0x00
@@ -41,6 +42,8 @@
/* Bit fields in CTRLR0 */
#define SPI_DFS_OFFSET 0
+#define SPI_DFS_MASK GENMASK(3, 0)
+#define SPI_DFS32_OFFSET 16
#define SPI_FRF_OFFSET 4
#define SPI_FRF_SPI 0x0
@@ -121,6 +124,7 @@ enum dw_ssi_type {
#define DW_SPI_CAP_CS_OVERRIDE BIT(0)
#define DW_SPI_CAP_KEEMBAY_MST BIT(1)
#define DW_SPI_CAP_DWC_SSI BIT(2)
+#define DW_SPI_CAP_DFS32 BIT(3)
/* Slave spi_transfer/spi_mem_op related */
struct dw_spi_cfg {
@@ -148,6 +152,7 @@ struct dw_spi {
unsigned long paddr;
int irq;
u32 fifo_len; /* depth of the FIFO buffer */
+ unsigned int dfs_offset; /* CTRLR0 DFS field offset */
u32 max_mem_freq; /* max mem-ops bus freq */
u32 max_freq; /* max bus freq supported */
diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c
index 8a440c7078ef..3920cd3286d8 100644
--- a/drivers/spi/spi-fsi.c
+++ b/drivers/spi/spi-fsi.c
@@ -477,7 +477,7 @@ static int fsi_spi_transfer_one_message(struct spi_controller *ctlr,
rc = fsi_spi_check_mux(ctx->fsi, ctx->dev);
if (rc)
- return rc;
+ goto error;
list_for_each_entry(transfer, &mesg->transfers, transfer_list) {
struct fsi_spi_sequence seq;
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 1a08c1d584ab..028736687488 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -1165,7 +1165,7 @@ static int dspi_init(struct fsl_dspi *dspi)
unsigned int mcr;
/* Set idle states for all chip select signals to high */
- mcr = SPI_MCR_PCSIS(GENMASK(dspi->ctlr->num_chipselect - 1, 0));
+ mcr = SPI_MCR_PCSIS(GENMASK(dspi->ctlr->max_native_cs - 1, 0));
if (dspi->devtype_data->trans_mode == DSPI_XSPI_MODE)
mcr |= SPI_MCR_XSPI;
@@ -1250,7 +1250,7 @@ static int dspi_probe(struct platform_device *pdev)
pdata = dev_get_platdata(&pdev->dev);
if (pdata) {
- ctlr->num_chipselect = pdata->cs_num;
+ ctlr->num_chipselect = ctlr->max_native_cs = pdata->cs_num;
ctlr->bus_num = pdata->bus_num;
/* Only Coldfire uses platform data */
@@ -1263,7 +1263,7 @@ static int dspi_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "can't get spi-num-chipselects\n");
goto out_ctlr_put;
}
- ctlr->num_chipselect = cs_num;
+ ctlr->num_chipselect = ctlr->max_native_cs = cs_num;
of_property_read_u32(np, "bus-num", &bus_num);
ctlr->bus_num = bus_num;
diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
index 986b9793fd3c..a2886ee44e4c 100644
--- a/drivers/spi/spi-fsl-lpspi.c
+++ b/drivers/spi/spi-fsl-lpspi.c
@@ -938,9 +938,6 @@ static int fsl_lpspi_remove(struct platform_device *pdev)
spi_controller_get_devdata(controller);
pm_runtime_disable(fsl_lpspi->dev);
-
- spi_master_put(controller);
-
return 0;
}
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
index 299e9870cf58..9494257e1c33 100644
--- a/drivers/spi/spi-fsl-spi.c
+++ b/drivers/spi/spi-fsl-spi.c
@@ -716,10 +716,11 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
type = fsl_spi_get_type(&ofdev->dev);
if (type == TYPE_FSL) {
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
+ bool spisel_boot = false;
#if IS_ENABLED(CONFIG_FSL_SOC)
struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
- bool spisel_boot = of_property_read_bool(np, "fsl,spisel_boot");
+ spisel_boot = of_property_read_bool(np, "fsl,spisel_boot");
if (spisel_boot) {
pinfo->immr_spi_cs = ioremap(get_immrbase() + IMMR_SPI_CS_OFFSET, 4);
if (!pinfo->immr_spi_cs)
@@ -734,10 +735,14 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
* supported on the GRLIB variant.
*/
ret = gpiod_count(dev, "cs");
- if (ret <= 0)
+ if (ret < 0)
+ ret = 0;
+ if (ret == 0 && !spisel_boot) {
pdata->max_chipselect = 1;
- else
+ } else {
+ pdata->max_chipselect = ret + spisel_boot;
pdata->cs_control = fsl_spi_cs_control;
+ }
}
ret = of_address_to_resource(np, 0, &mem);
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index 25810a7eef10..512e925d5ea4 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -603,7 +603,7 @@ static int spi_geni_probe(struct platform_device *pdev)
if (IS_ERR(clk))
return PTR_ERR(clk);
- spi = spi_alloc_master(dev, sizeof(*mas));
+ spi = devm_spi_alloc_master(dev, sizeof(*mas));
if (!spi)
return -ENOMEM;
@@ -636,6 +636,7 @@ static int spi_geni_probe(struct platform_device *pdev)
spi->auto_runtime_pm = true;
spi->handle_err = handle_fifo_timeout;
spi->set_cs = spi_geni_set_cs;
+ spi->use_gpio_descriptors = true;
init_completion(&mas->cs_done);
init_completion(&mas->cancel_done);
@@ -673,7 +674,6 @@ spi_geni_probe_free_irq:
free_irq(mas->irq, spi);
spi_geni_probe_runtime_disable:
pm_runtime_disable(dev);
- spi_master_put(spi);
dev_pm_opp_of_remove_table(&pdev->dev);
put_clkname:
dev_pm_opp_put_clkname(mas->se.opp_table);
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index 7ceb0ba27b75..0584f4d2fde2 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -350,11 +350,6 @@ static int spi_gpio_probe_pdata(struct platform_device *pdev,
return 0;
}
-static void spi_gpio_put(void *data)
-{
- spi_master_put(data);
-}
-
static int spi_gpio_probe(struct platform_device *pdev)
{
int status;
@@ -363,16 +358,10 @@ static int spi_gpio_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct spi_bitbang *bb;
- master = spi_alloc_master(dev, sizeof(*spi_gpio));
+ master = devm_spi_alloc_master(dev, sizeof(*spi_gpio));
if (!master)
return -ENOMEM;
- status = devm_add_action_or_reset(&pdev->dev, spi_gpio_put, master);
- if (status) {
- spi_master_put(master);
- return status;
- }
-
if (pdev->dev.of_node)
status = spi_gpio_probe_dt(pdev, master);
else
@@ -432,7 +421,7 @@ static int spi_gpio_probe(struct platform_device *pdev)
if (status)
return status;
- return devm_spi_register_master(&pdev->dev, spi_master_get(master));
+ return devm_spi_register_master(&pdev->dev, master);
}
MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c
index b068537375d6..5f05d519fbbd 100644
--- a/drivers/spi/spi-img-spfi.c
+++ b/drivers/spi/spi-img-spfi.c
@@ -731,8 +731,10 @@ static int img_spfi_resume(struct device *dev)
int ret;
ret = pm_runtime_get_sync(dev);
- if (ret)
+ if (ret) {
+ pm_runtime_put_noidle(dev);
return ret;
+ }
spfi_reset(spfi);
pm_runtime_put(dev);
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 4b80e27ecdbf..73ca821763d6 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -1019,33 +1019,6 @@ static struct spi_imx_devtype_data imx53_ecspi_devtype_data = {
.devtype = IMX53_ECSPI,
};
-static const struct platform_device_id spi_imx_devtype[] = {
- {
- .name = "imx1-cspi",
- .driver_data = (kernel_ulong_t) &imx1_cspi_devtype_data,
- }, {
- .name = "imx21-cspi",
- .driver_data = (kernel_ulong_t) &imx21_cspi_devtype_data,
- }, {
- .name = "imx27-cspi",
- .driver_data = (kernel_ulong_t) &imx27_cspi_devtype_data,
- }, {
- .name = "imx31-cspi",
- .driver_data = (kernel_ulong_t) &imx31_cspi_devtype_data,
- }, {
- .name = "imx35-cspi",
- .driver_data = (kernel_ulong_t) &imx35_cspi_devtype_data,
- }, {
- .name = "imx51-ecspi",
- .driver_data = (kernel_ulong_t) &imx51_ecspi_devtype_data,
- }, {
- .name = "imx53-ecspi",
- .driver_data = (kernel_ulong_t) &imx53_ecspi_devtype_data,
- }, {
- /* sentinel */
- }
-};
-
static const struct of_device_id spi_imx_dt_ids[] = {
{ .compatible = "fsl,imx1-cspi", .data = &imx1_cspi_devtype_data, },
{ .compatible = "fsl,imx21-cspi", .data = &imx21_cspi_devtype_data, },
@@ -1538,6 +1511,7 @@ spi_imx_prepare_message(struct spi_master *master, struct spi_message *msg)
ret = pm_runtime_get_sync(spi_imx->dev);
if (ret < 0) {
+ pm_runtime_put_noidle(spi_imx->dev);
dev_err(spi_imx->dev, "failed to enable clock\n");
return ret;
}
@@ -1580,8 +1554,7 @@ static int spi_imx_probe(struct platform_device *pdev)
struct spi_imx_data *spi_imx;
struct resource *res;
int ret, irq, spi_drctl;
- const struct spi_imx_devtype_data *devtype_data = of_id ? of_id->data :
- (struct spi_imx_devtype_data *)pdev->id_entry->driver_data;
+ const struct spi_imx_devtype_data *devtype_data = of_id->data;
bool slave_mode;
u32 val;
@@ -1686,6 +1659,7 @@ static int spi_imx_probe(struct platform_device *pdev)
pm_runtime_set_autosuspend_delay(spi_imx->dev, MXC_RPM_TIMEOUT);
pm_runtime_use_autosuspend(spi_imx->dev);
+ pm_runtime_get_noresume(spi_imx->dev);
pm_runtime_set_active(spi_imx->dev);
pm_runtime_enable(spi_imx->dev);
@@ -1747,6 +1721,7 @@ static int spi_imx_remove(struct platform_device *pdev)
ret = pm_runtime_get_sync(spi_imx->dev);
if (ret < 0) {
+ pm_runtime_put_noidle(spi_imx->dev);
dev_err(spi_imx->dev, "failed to enable clock\n");
return ret;
}
@@ -1821,7 +1796,6 @@ static struct platform_driver spi_imx_driver = {
.of_match_table = spi_imx_dt_ids,
.pm = &imx_spi_pm,
},
- .id_table = spi_imx_devtype,
.probe = spi_imx_probe,
.remove = spi_imx_remove,
};
diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
index ef53290b7d24..f3a3f196e628 100644
--- a/drivers/spi/spi-mem.c
+++ b/drivers/spi/spi-mem.c
@@ -243,6 +243,7 @@ static int spi_mem_access_start(struct spi_mem *mem)
ret = pm_runtime_get_sync(ctlr->dev.parent);
if (ret < 0) {
+ pm_runtime_put_noidle(ctlr->dev.parent);
dev_err(&ctlr->dev, "Failed to power device: %d\n",
ret);
return ret;
@@ -743,7 +744,7 @@ static int spi_mem_probe(struct spi_device *spi)
mem->name = dev_name(&spi->dev);
if (IS_ERR_OR_NULL(mem->name))
- return PTR_ERR(mem->name);
+ return PTR_ERR_OR_ZERO(mem->name);
spi_set_drvdata(spi, mem);
diff --git a/drivers/spi/spi-mt7621.c b/drivers/spi/spi-mt7621.c
index 2c3b7a2a1ec7..b4b9b7309b5e 100644
--- a/drivers/spi/spi-mt7621.c
+++ b/drivers/spi/spi-mt7621.c
@@ -350,9 +350,10 @@ static int mt7621_spi_probe(struct platform_device *pdev)
if (status)
return status;
- master = spi_alloc_master(&pdev->dev, sizeof(*rs));
+ master = devm_spi_alloc_master(&pdev->dev, sizeof(*rs));
if (!master) {
dev_info(&pdev->dev, "master allocation failed\n");
+ clk_disable_unprepare(clk);
return -ENOMEM;
}
@@ -377,10 +378,15 @@ static int mt7621_spi_probe(struct platform_device *pdev)
ret = device_reset(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "SPI reset failed!\n");
+ clk_disable_unprepare(clk);
return ret;
}
- return devm_spi_register_controller(&pdev->dev, master);
+ ret = spi_register_controller(master);
+ if (ret)
+ clk_disable_unprepare(clk);
+
+ return ret;
}
static int mt7621_spi_remove(struct platform_device *pdev)
@@ -391,6 +397,7 @@ static int mt7621_spi_remove(struct platform_device *pdev)
master = dev_get_drvdata(&pdev->dev);
rs = spi_controller_get_devdata(master);
+ spi_unregister_controller(master);
clk_disable_unprepare(rs->clk);
return 0;
diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c
index b97f26a60cbe..2e2f36a2e385 100644
--- a/drivers/spi/spi-mtk-nor.c
+++ b/drivers/spi/spi-mtk-nor.c
@@ -103,6 +103,7 @@ struct mtk_nor {
dma_addr_t buffer_dma;
struct clk *spi_clk;
struct clk *ctlr_clk;
+ struct clk *axi_clk;
unsigned int spi_freq;
bool wbuf_en;
bool has_irq;
@@ -672,6 +673,7 @@ static void mtk_nor_disable_clk(struct mtk_nor *sp)
{
clk_disable_unprepare(sp->spi_clk);
clk_disable_unprepare(sp->ctlr_clk);
+ clk_disable_unprepare(sp->axi_clk);
}
static int mtk_nor_enable_clk(struct mtk_nor *sp)
@@ -688,6 +690,13 @@ static int mtk_nor_enable_clk(struct mtk_nor *sp)
return ret;
}
+ ret = clk_prepare_enable(sp->axi_clk);
+ if (ret) {
+ clk_disable_unprepare(sp->spi_clk);
+ clk_disable_unprepare(sp->ctlr_clk);
+ return ret;
+ }
+
return 0;
}
@@ -746,7 +755,7 @@ static int mtk_nor_probe(struct platform_device *pdev)
struct spi_controller *ctlr;
struct mtk_nor *sp;
void __iomem *base;
- struct clk *spi_clk, *ctlr_clk;
+ struct clk *spi_clk, *ctlr_clk, *axi_clk;
int ret, irq;
unsigned long dma_bits;
@@ -762,13 +771,17 @@ static int mtk_nor_probe(struct platform_device *pdev)
if (IS_ERR(ctlr_clk))
return PTR_ERR(ctlr_clk);
+ axi_clk = devm_clk_get_optional(&pdev->dev, "axi");
+ if (IS_ERR(axi_clk))
+ return PTR_ERR(axi_clk);
+
dma_bits = (unsigned long)of_device_get_match_data(&pdev->dev);
if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(dma_bits))) {
dev_err(&pdev->dev, "failed to set dma mask(%lu)\n", dma_bits);
return -EINVAL;
}
- ctlr = spi_alloc_master(&pdev->dev, sizeof(*sp));
+ ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*sp));
if (!ctlr) {
dev_err(&pdev->dev, "failed to allocate spi controller\n");
return -ENOMEM;
@@ -794,6 +807,7 @@ static int mtk_nor_probe(struct platform_device *pdev)
sp->dev = &pdev->dev;
sp->spi_clk = spi_clk;
sp->ctlr_clk = ctlr_clk;
+ sp->axi_clk = axi_clk;
sp->high_dma = (dma_bits > 32);
sp->buffer = dmam_alloc_coherent(&pdev->dev,
MTK_NOR_BOUNCE_BUF_SIZE + MTK_NOR_DMA_ALIGN,
diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
index 8c630acb0110..96b418293bf2 100644
--- a/drivers/spi/spi-mxic.c
+++ b/drivers/spi/spi-mxic.c
@@ -529,7 +529,7 @@ static int mxic_spi_probe(struct platform_device *pdev)
struct mxic_spi *mxic;
int ret;
- master = spi_alloc_master(&pdev->dev, sizeof(struct mxic_spi));
+ master = devm_spi_alloc_master(&pdev->dev, sizeof(struct mxic_spi));
if (!master)
return -ENOMEM;
@@ -574,15 +574,9 @@ static int mxic_spi_probe(struct platform_device *pdev)
ret = spi_register_master(master);
if (ret) {
dev_err(&pdev->dev, "spi_register_master failed\n");
- goto err_put_master;
+ pm_runtime_disable(&pdev->dev);
}
- return 0;
-
-err_put_master:
- spi_master_put(master);
- pm_runtime_disable(&pdev->dev);
-
return ret;
}
diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c
index 918918a9e049..435309b09227 100644
--- a/drivers/spi/spi-mxs.c
+++ b/drivers/spi/spi-mxs.c
@@ -607,6 +607,7 @@ static int mxs_spi_probe(struct platform_device *pdev)
ret = pm_runtime_get_sync(ssp->dev);
if (ret < 0) {
+ pm_runtime_put_noidle(ssp->dev);
dev_err(ssp->dev, "runtime_get_sync failed\n");
goto out_pm_runtime_disable;
}
diff --git a/drivers/spi/spi-npcm-fiu.c b/drivers/spi/spi-npcm-fiu.c
index 341f7cffeaac..b62471ab6d7f 100644
--- a/drivers/spi/spi-npcm-fiu.c
+++ b/drivers/spi/spi-npcm-fiu.c
@@ -677,9 +677,9 @@ static int npcm_fiu_probe(struct platform_device *pdev)
struct npcm_fiu_spi *fiu;
void __iomem *regbase;
struct resource *res;
- int id;
+ int id, ret;
- ctrl = spi_alloc_master(dev, sizeof(*fiu));
+ ctrl = devm_spi_alloc_master(dev, sizeof(*fiu));
if (!ctrl)
return -ENOMEM;
@@ -735,7 +735,11 @@ static int npcm_fiu_probe(struct platform_device *pdev)
ctrl->num_chipselect = fiu->info->max_cs;
ctrl->dev.of_node = dev->of_node;
- return devm_spi_register_master(dev, ctrl);
+ ret = devm_spi_register_master(dev, ctrl);
+ if (ret)
+ clk_disable_unprepare(fiu->clk);
+
+ return ret;
}
static int npcm_fiu_remove(struct platform_device *pdev)
diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
index 0d41406c036d..ab9035662717 100644
--- a/drivers/spi/spi-nxp-fspi.c
+++ b/drivers/spi/spi-nxp-fspi.c
@@ -1001,6 +1001,7 @@ static int nxp_fspi_probe(struct platform_device *pdev)
struct resource *res;
struct nxp_fspi *f;
int ret;
+ u32 reg;
ctlr = spi_alloc_master(&pdev->dev, sizeof(*f));
if (!ctlr)
@@ -1032,6 +1033,12 @@ static int nxp_fspi_probe(struct platform_device *pdev)
goto err_put_ctrl;
}
+ /* Clear potential interrupts */
+ reg = fspi_readl(f, f->iobase + FSPI_INTR);
+ if (reg)
+ fspi_writel(f, reg, f->iobase + FSPI_INTR);
+
+
/* find the resources - controller memory mapped space */
if (is_acpi_node(f->dev->fwnode))
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c
index 156961b4ca86..104bde153efd 100644
--- a/drivers/spi/spi-pic32.c
+++ b/drivers/spi/spi-pic32.c
@@ -839,6 +839,7 @@ static int pic32_spi_probe(struct platform_device *pdev)
return 0;
err_bailout:
+ pic32_spi_dma_unprep(pic32s);
clk_disable_unprepare(pic32s->clk);
err_master:
spi_master_put(master);
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index 814268405ab0..bd2354fd438d 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -1496,6 +1496,11 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
{ PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x5ac6), LPSS_BXT_SSP },
+ /* ADL-S */
+ { PCI_VDEVICE(INTEL, 0x7aaa), LPSS_CNL_SSP },
+ { PCI_VDEVICE(INTEL, 0x7aab), LPSS_CNL_SSP },
+ { PCI_VDEVICE(INTEL, 0x7af9), LPSS_CNL_SSP },
+ { PCI_VDEVICE(INTEL, 0x7afb), LPSS_CNL_SSP },
/* CNL-LP */
{ PCI_VDEVICE(INTEL, 0x9daa), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x9dab), LPSS_CNL_SSP },
@@ -1686,9 +1691,9 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
}
if (platform_info->is_slave)
- controller = spi_alloc_slave(dev, sizeof(struct driver_data));
+ controller = devm_spi_alloc_slave(dev, sizeof(*drv_data));
else
- controller = spi_alloc_master(dev, sizeof(struct driver_data));
+ controller = devm_spi_alloc_master(dev, sizeof(*drv_data));
if (!controller) {
dev_err(&pdev->dev, "cannot alloc spi_controller\n");
@@ -1911,7 +1916,6 @@ out_error_dma_irq_alloc:
free_irq(ssp->irq, drv_data);
out_error_controller_alloc:
- spi_controller_put(controller);
pxa_ssp_free(ssp);
return status;
}
diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c
index 5eed88af6899..8863be370884 100644
--- a/drivers/spi/spi-qcom-qspi.c
+++ b/drivers/spi/spi-qcom-qspi.c
@@ -462,7 +462,7 @@ static int qcom_qspi_probe(struct platform_device *pdev)
dev = &pdev->dev;
- master = spi_alloc_master(dev, sizeof(*ctrl));
+ master = devm_spi_alloc_master(dev, sizeof(*ctrl));
if (!master)
return -ENOMEM;
@@ -473,54 +473,49 @@ static int qcom_qspi_probe(struct platform_device *pdev)
spin_lock_init(&ctrl->lock);
ctrl->dev = dev;
ctrl->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(ctrl->base)) {
- ret = PTR_ERR(ctrl->base);
- goto exit_probe_master_put;
- }
+ if (IS_ERR(ctrl->base))
+ return PTR_ERR(ctrl->base);
ctrl->clks = devm_kcalloc(dev, QSPI_NUM_CLKS,
sizeof(*ctrl->clks), GFP_KERNEL);
- if (!ctrl->clks) {
- ret = -ENOMEM;
- goto exit_probe_master_put;
- }
+ if (!ctrl->clks)
+ return -ENOMEM;
ctrl->clks[QSPI_CLK_CORE].id = "core";
ctrl->clks[QSPI_CLK_IFACE].id = "iface";
ret = devm_clk_bulk_get(dev, QSPI_NUM_CLKS, ctrl->clks);
if (ret)
- goto exit_probe_master_put;
+ return ret;
ctrl->icc_path_cpu_to_qspi = devm_of_icc_get(dev, "qspi-config");
- if (IS_ERR(ctrl->icc_path_cpu_to_qspi)) {
- ret = dev_err_probe(dev, PTR_ERR(ctrl->icc_path_cpu_to_qspi),
- "Failed to get cpu path\n");
- goto exit_probe_master_put;
- }
+ if (IS_ERR(ctrl->icc_path_cpu_to_qspi))
+ return dev_err_probe(dev, PTR_ERR(ctrl->icc_path_cpu_to_qspi),
+ "Failed to get cpu path\n");
+
/* Set BW vote for register access */
ret = icc_set_bw(ctrl->icc_path_cpu_to_qspi, Bps_to_icc(1000),
Bps_to_icc(1000));
if (ret) {
dev_err(ctrl->dev, "%s: ICC BW voting failed for cpu: %d\n",
__func__, ret);
- goto exit_probe_master_put;
+ return ret;
}
ret = icc_disable(ctrl->icc_path_cpu_to_qspi);
if (ret) {
dev_err(ctrl->dev, "%s: ICC disable failed for cpu: %d\n",
__func__, ret);
- goto exit_probe_master_put;
+ return ret;
}
ret = platform_get_irq(pdev, 0);
if (ret < 0)
- goto exit_probe_master_put;
+ return ret;
ret = devm_request_irq(dev, ret, qcom_qspi_irq,
IRQF_TRIGGER_HIGH, dev_name(dev), ctrl);
if (ret) {
dev_err(dev, "Failed to request irq %d\n", ret);
- goto exit_probe_master_put;
+ return ret;
}
master->max_speed_hz = 300000000;
@@ -537,10 +532,8 @@ static int qcom_qspi_probe(struct platform_device *pdev)
master->auto_runtime_pm = true;
ctrl->opp_table = dev_pm_opp_set_clkname(&pdev->dev, "core");
- if (IS_ERR(ctrl->opp_table)) {
- ret = PTR_ERR(ctrl->opp_table);
- goto exit_probe_master_put;
- }
+ if (IS_ERR(ctrl->opp_table))
+ return PTR_ERR(ctrl->opp_table);
/* OPP table is optional */
ret = dev_pm_opp_of_add_table(&pdev->dev);
if (ret && ret != -ENODEV) {
@@ -562,9 +555,6 @@ static int qcom_qspi_probe(struct platform_device *pdev)
exit_probe_put_clkname:
dev_pm_opp_put_clkname(ctrl->opp_table);
-exit_probe_master_put:
- spi_master_put(master);
-
return ret;
}
diff --git a/drivers/spi/spi-rb4xx.c b/drivers/spi/spi-rb4xx.c
index 8aa51beb4ff3..9f97d18a05c1 100644
--- a/drivers/spi/spi-rb4xx.c
+++ b/drivers/spi/spi-rb4xx.c
@@ -143,7 +143,7 @@ static int rb4xx_spi_probe(struct platform_device *pdev)
if (IS_ERR(spi_base))
return PTR_ERR(spi_base);
- master = spi_alloc_master(&pdev->dev, sizeof(*rbspi));
+ master = devm_spi_alloc_master(&pdev->dev, sizeof(*rbspi));
if (!master)
return -ENOMEM;
diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 75a8a9428ff8..09d8e92400eb 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -160,6 +160,8 @@
#define ROCKCHIP_SPI_VER2_TYPE1 0x05EC0002
#define ROCKCHIP_SPI_VER2_TYPE2 0x00110002
+#define ROCKCHIP_AUTOSUSPEND_TIMEOUT 2000
+
struct rockchip_spi {
struct device *dev;
@@ -715,6 +717,8 @@ static int rockchip_spi_probe(struct platform_device *pdev)
goto err_disable_spiclk;
}
+ pm_runtime_set_autosuspend_delay(&pdev->dev, ROCKCHIP_AUTOSUSPEND_TIMEOUT);
+ pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
diff --git a/drivers/spi/spi-rpc-if.c b/drivers/spi/spi-rpc-if.c
index ed3e548227f4..3579675485a5 100644
--- a/drivers/spi/spi-rpc-if.c
+++ b/drivers/spi/spi-rpc-if.c
@@ -134,7 +134,7 @@ static int rpcif_spi_probe(struct platform_device *pdev)
struct rpcif *rpc;
int error;
- ctlr = spi_alloc_master(&pdev->dev, sizeof(*rpc));
+ ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*rpc));
if (!ctlr)
return -ENOMEM;
@@ -159,13 +159,8 @@ static int rpcif_spi_probe(struct platform_device *pdev)
error = spi_register_controller(ctlr);
if (error) {
dev_err(&pdev->dev, "spi_register_controller failed\n");
- goto err_put_ctlr;
+ rpcif_disable_rpm(rpc);
}
- return 0;
-
-err_put_ctlr:
- rpcif_disable_rpm(rpc);
- spi_controller_put(ctlr);
return error;
}
diff --git a/drivers/spi/spi-sc18is602.c b/drivers/spi/spi-sc18is602.c
index ee0f3edf49cd..297c512069a5 100644
--- a/drivers/spi/spi-sc18is602.c
+++ b/drivers/spi/spi-sc18is602.c
@@ -238,13 +238,12 @@ static int sc18is602_probe(struct i2c_client *client,
struct sc18is602_platform_data *pdata = dev_get_platdata(dev);
struct sc18is602 *hw;
struct spi_master *master;
- int error;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
return -EINVAL;
- master = spi_alloc_master(dev, sizeof(struct sc18is602));
+ master = devm_spi_alloc_master(dev, sizeof(struct sc18is602));
if (!master)
return -ENOMEM;
@@ -298,15 +297,7 @@ static int sc18is602_probe(struct i2c_client *client,
master->min_speed_hz = hw->freq / 128;
master->max_speed_hz = hw->freq / 4;
- error = devm_spi_register_master(dev, master);
- if (error)
- goto error_reg;
-
- return 0;
-
-error_reg:
- spi_master_put(master);
- return error;
+ return devm_spi_register_master(dev, master);
}
static const struct i2c_device_id sc18is602_id[] = {
diff --git a/drivers/spi/spi-sh.c b/drivers/spi/spi-sh.c
index 20bdae5fdf3b..15123a8f41e1 100644
--- a/drivers/spi/spi-sh.c
+++ b/drivers/spi/spi-sh.c
@@ -440,7 +440,7 @@ static int spi_sh_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
- master = spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data));
+ master = devm_spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data));
if (master == NULL) {
dev_err(&pdev->dev, "spi_alloc_master error.\n");
return -ENOMEM;
@@ -458,16 +458,14 @@ static int spi_sh_probe(struct platform_device *pdev)
break;
default:
dev_err(&pdev->dev, "No support width\n");
- ret = -ENODEV;
- goto error1;
+ return -ENODEV;
}
ss->irq = irq;
ss->master = master;
ss->addr = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (ss->addr == NULL) {
dev_err(&pdev->dev, "ioremap error.\n");
- ret = -ENOMEM;
- goto error1;
+ return -ENOMEM;
}
INIT_LIST_HEAD(&ss->queue);
spin_lock_init(&ss->lock);
@@ -477,7 +475,7 @@ static int spi_sh_probe(struct platform_device *pdev)
ret = request_irq(irq, spi_sh_irq, 0, "spi_sh", ss);
if (ret < 0) {
dev_err(&pdev->dev, "request_irq error\n");
- goto error1;
+ return ret;
}
master->num_chipselect = 2;
@@ -496,9 +494,6 @@ static int spi_sh_probe(struct platform_device *pdev)
error3:
free_irq(irq, ss);
- error1:
- spi_master_put(master);
-
return ret;
}
diff --git a/drivers/spi/spi-sprd.c b/drivers/spi/spi-sprd.c
index 635738f54c73..b41a75749b49 100644
--- a/drivers/spi/spi-sprd.c
+++ b/drivers/spi/spi-sprd.c
@@ -1010,6 +1010,7 @@ static int sprd_spi_remove(struct platform_device *pdev)
ret = pm_runtime_get_sync(ss->dev);
if (ret < 0) {
+ pm_runtime_put_noidle(ss->dev);
dev_err(ss->dev, "failed to resume SPI controller\n");
return ret;
}
diff --git a/drivers/spi/spi-st-ssc4.c b/drivers/spi/spi-st-ssc4.c
index 77d26d64541a..6c44dda9ee8c 100644
--- a/drivers/spi/spi-st-ssc4.c
+++ b/drivers/spi/spi-st-ssc4.c
@@ -375,13 +375,14 @@ static int spi_st_probe(struct platform_device *pdev)
ret = devm_spi_register_master(&pdev->dev, master);
if (ret) {
dev_err(&pdev->dev, "Failed to register master\n");
- goto clk_disable;
+ goto rpm_disable;
}
return 0;
-clk_disable:
+rpm_disable:
pm_runtime_disable(&pdev->dev);
+clk_disable:
clk_disable_unprepare(spi_st->clk);
put_master:
spi_master_put(master);
diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c
index a900962b4336..947e6b9dc9f4 100644
--- a/drivers/spi/spi-stm32-qspi.c
+++ b/drivers/spi/spi-stm32-qspi.c
@@ -434,8 +434,10 @@ static int stm32_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
int ret;
ret = pm_runtime_get_sync(qspi->dev);
- if (ret < 0)
+ if (ret < 0) {
+ pm_runtime_put_noidle(qspi->dev);
return ret;
+ }
mutex_lock(&qspi->lock);
ret = stm32_qspi_send(mem, op);
@@ -462,8 +464,10 @@ static int stm32_qspi_setup(struct spi_device *spi)
return -EINVAL;
ret = pm_runtime_get_sync(qspi->dev);
- if (ret < 0)
+ if (ret < 0) {
+ pm_runtime_put_noidle(qspi->dev);
return ret;
+ }
presc = DIV_ROUND_UP(qspi->clk_rate, spi->max_speed_hz) - 1;
diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c
index 2cc850eb8922..471dedf3d339 100644
--- a/drivers/spi/spi-stm32.c
+++ b/drivers/spi/spi-stm32.c
@@ -2062,6 +2062,7 @@ static int stm32_spi_resume(struct device *dev)
ret = pm_runtime_get_sync(dev);
if (ret < 0) {
+ pm_runtime_put_noidle(dev);
dev_err(dev, "Unable to power device:%d\n", ret);
return ret;
}
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 19238e1b76b4..cc8401980125 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -18,9 +18,12 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
+#include <linux/dmaengine.h>
#include <linux/spi/spi.h>
+#define SUN6I_AUTOSUSPEND_TIMEOUT 2000
+
#define SUN6I_FIFO_DEPTH 128
#define SUN8I_FIFO_DEPTH 64
@@ -52,10 +55,12 @@
#define SUN6I_FIFO_CTL_REG 0x18
#define SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_MASK 0xff
+#define SUN6I_FIFO_CTL_RF_DRQ_EN BIT(8)
#define SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS 0
#define SUN6I_FIFO_CTL_RF_RST BIT(15)
#define SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_MASK 0xff
#define SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS 16
+#define SUN6I_FIFO_CTL_TF_DRQ_EN BIT(24)
#define SUN6I_FIFO_CTL_TF_RST BIT(31)
#define SUN6I_FIFO_STA_REG 0x1c
@@ -83,6 +88,8 @@
struct sun6i_spi {
struct spi_master *master;
void __iomem *base_addr;
+ dma_addr_t dma_addr_rx;
+ dma_addr_t dma_addr_tx;
struct clk *hclk;
struct clk *mclk;
struct reset_control *rstc;
@@ -182,6 +189,68 @@ static size_t sun6i_spi_max_transfer_size(struct spi_device *spi)
return SUN6I_MAX_XFER_SIZE - 1;
}
+static int sun6i_spi_prepare_dma(struct sun6i_spi *sspi,
+ struct spi_transfer *tfr)
+{
+ struct dma_async_tx_descriptor *rxdesc, *txdesc;
+ struct spi_master *master = sspi->master;
+
+ rxdesc = NULL;
+ if (tfr->rx_buf) {
+ struct dma_slave_config rxconf = {
+ .direction = DMA_DEV_TO_MEM,
+ .src_addr = sspi->dma_addr_rx,
+ .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+ .src_maxburst = 8,
+ };
+
+ dmaengine_slave_config(master->dma_rx, &rxconf);
+
+ rxdesc = dmaengine_prep_slave_sg(master->dma_rx,
+ tfr->rx_sg.sgl,
+ tfr->rx_sg.nents,
+ DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT);
+ if (!rxdesc)
+ return -EINVAL;
+ }
+
+ txdesc = NULL;
+ if (tfr->tx_buf) {
+ struct dma_slave_config txconf = {
+ .direction = DMA_MEM_TO_DEV,
+ .dst_addr = sspi->dma_addr_tx,
+ .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+ .dst_maxburst = 8,
+ };
+
+ dmaengine_slave_config(master->dma_tx, &txconf);
+
+ txdesc = dmaengine_prep_slave_sg(master->dma_tx,
+ tfr->tx_sg.sgl,
+ tfr->tx_sg.nents,
+ DMA_MEM_TO_DEV,
+ DMA_PREP_INTERRUPT);
+ if (!txdesc) {
+ if (rxdesc)
+ dmaengine_terminate_sync(master->dma_rx);
+ return -EINVAL;
+ }
+ }
+
+ if (tfr->rx_buf) {
+ dmaengine_submit(rxdesc);
+ dma_async_issue_pending(master->dma_rx);
+ }
+
+ if (tfr->tx_buf) {
+ dmaengine_submit(txdesc);
+ dma_async_issue_pending(master->dma_tx);
+ }
+
+ return 0;
+}
+
static int sun6i_spi_transfer_one(struct spi_master *master,
struct spi_device *spi,
struct spi_transfer *tfr)
@@ -191,6 +260,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
unsigned int start, end, tx_time;
unsigned int trig_level;
unsigned int tx_len = 0, rx_len = 0;
+ bool use_dma;
int ret = 0;
u32 reg;
@@ -201,6 +271,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
sspi->tx_buf = tfr->tx_buf;
sspi->rx_buf = tfr->rx_buf;
sspi->len = tfr->len;
+ use_dma = master->can_dma ? master->can_dma(master, spi, tfr) : false;
/* Clear pending interrupts */
sun6i_spi_write(sspi, SUN6I_INT_STA_REG, ~0);
@@ -209,16 +280,34 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG,
SUN6I_FIFO_CTL_RF_RST | SUN6I_FIFO_CTL_TF_RST);
- /*
- * Setup FIFO interrupt trigger level
- * Here we choose 3/4 of the full fifo depth, as it's the hardcoded
- * value used in old generation of Allwinner SPI controller.
- * (See spi-sun4i.c)
- */
- trig_level = sspi->fifo_depth / 4 * 3;
- sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG,
- (trig_level << SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS) |
- (trig_level << SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS));
+ reg = 0;
+
+ if (!use_dma) {
+ /*
+ * Setup FIFO interrupt trigger level
+ * Here we choose 3/4 of the full fifo depth, as it's
+ * the hardcoded value used in old generation of Allwinner
+ * SPI controller. (See spi-sun4i.c)
+ */
+ trig_level = sspi->fifo_depth / 4 * 3;
+ } else {
+ /*
+ * Setup FIFO DMA request trigger level
+ * We choose 1/2 of the full fifo depth, that value will
+ * be used as DMA burst length.
+ */
+ trig_level = sspi->fifo_depth / 2;
+
+ if (tfr->tx_buf)
+ reg |= SUN6I_FIFO_CTL_TF_DRQ_EN;
+ if (tfr->rx_buf)
+ reg |= SUN6I_FIFO_CTL_RF_DRQ_EN;
+ }
+
+ reg |= (trig_level << SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS) |
+ (trig_level << SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS);
+
+ sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG, reg);
/*
* Setup the transfer control register: Chip Select,
@@ -300,16 +389,28 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
sun6i_spi_write(sspi, SUN6I_XMIT_CNT_REG, tx_len);
sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG, tx_len);
- /* Fill the TX FIFO */
- sun6i_spi_fill_fifo(sspi);
+ if (!use_dma) {
+ /* Fill the TX FIFO */
+ sun6i_spi_fill_fifo(sspi);
+ } else {
+ ret = sun6i_spi_prepare_dma(sspi, tfr);
+ if (ret) {
+ dev_warn(&master->dev,
+ "%s: prepare DMA failed, ret=%d",
+ dev_name(&spi->dev), ret);
+ return ret;
+ }
+ }
/* Enable the interrupts */
reg = SUN6I_INT_CTL_TC;
- if (rx_len > sspi->fifo_depth)
- reg |= SUN6I_INT_CTL_RF_RDY;
- if (tx_len > sspi->fifo_depth)
- reg |= SUN6I_INT_CTL_TF_ERQ;
+ if (!use_dma) {
+ if (rx_len > sspi->fifo_depth)
+ reg |= SUN6I_INT_CTL_RF_RDY;
+ if (tx_len > sspi->fifo_depth)
+ reg |= SUN6I_INT_CTL_TF_ERQ;
+ }
sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, reg);
@@ -332,6 +433,11 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0);
+ if (ret && use_dma) {
+ dmaengine_terminate_sync(master->dma_rx);
+ dmaengine_terminate_sync(master->dma_tx);
+ }
+
return ret;
}
@@ -422,10 +528,25 @@ static int sun6i_spi_runtime_suspend(struct device *dev)
return 0;
}
+static bool sun6i_spi_can_dma(struct spi_master *master,
+ struct spi_device *spi,
+ struct spi_transfer *xfer)
+{
+ struct sun6i_spi *sspi = spi_master_get_devdata(master);
+
+ /*
+ * If the number of spi words to transfer is less or equal than
+ * the fifo length we can just fill the fifo and wait for a single
+ * irq, so don't bother setting up dma
+ */
+ return xfer->len > sspi->fifo_depth;
+}
+
static int sun6i_spi_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct sun6i_spi *sspi;
+ struct resource *mem;
int ret = 0, irq;
master = spi_alloc_master(&pdev->dev, sizeof(struct sun6i_spi));
@@ -437,7 +558,7 @@ static int sun6i_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, master);
sspi = spi_master_get_devdata(master);
- sspi->base_addr = devm_platform_ioremap_resource(pdev, 0);
+ sspi->base_addr = devm_platform_get_and_ioremap_resource(pdev, 0, &mem);
if (IS_ERR(sspi->base_addr)) {
ret = PTR_ERR(sspi->base_addr);
goto err_free_master;
@@ -494,6 +615,33 @@ static int sun6i_spi_probe(struct platform_device *pdev)
goto err_free_master;
}
+ master->dma_tx = dma_request_chan(&pdev->dev, "tx");
+ if (IS_ERR(master->dma_tx)) {
+ /* Check tx to see if we need defer probing driver */
+ if (PTR_ERR(master->dma_tx) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto err_free_master;
+ }
+ dev_warn(&pdev->dev, "Failed to request TX DMA channel\n");
+ master->dma_tx = NULL;
+ }
+
+ master->dma_rx = dma_request_chan(&pdev->dev, "rx");
+ if (IS_ERR(master->dma_rx)) {
+ if (PTR_ERR(master->dma_rx) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto err_free_dma_tx;
+ }
+ dev_warn(&pdev->dev, "Failed to request RX DMA channel\n");
+ master->dma_rx = NULL;
+ }
+
+ if (master->dma_tx && master->dma_rx) {
+ sspi->dma_addr_tx = mem->start + SUN6I_TXDATA_REG;
+ sspi->dma_addr_rx = mem->start + SUN6I_RXDATA_REG;
+ master->can_dma = sun6i_spi_can_dma;
+ }
+
/*
* This wake-up/shutdown pattern is to be able to have the
* device woken up, even if runtime_pm is disabled
@@ -501,12 +649,13 @@ static int sun6i_spi_probe(struct platform_device *pdev)
ret = sun6i_spi_runtime_resume(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "Couldn't resume the device\n");
- goto err_free_master;
+ goto err_free_dma_rx;
}
+ pm_runtime_set_autosuspend_delay(&pdev->dev, SUN6I_AUTOSUSPEND_TIMEOUT);
+ pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
- pm_runtime_idle(&pdev->dev);
ret = devm_spi_register_master(&pdev->dev, master);
if (ret) {
@@ -519,6 +668,12 @@ static int sun6i_spi_probe(struct platform_device *pdev)
err_pm_disable:
pm_runtime_disable(&pdev->dev);
sun6i_spi_runtime_suspend(&pdev->dev);
+err_free_dma_rx:
+ if (master->dma_rx)
+ dma_release_channel(master->dma_rx);
+err_free_dma_tx:
+ if (master->dma_tx)
+ dma_release_channel(master->dma_tx);
err_free_master:
spi_master_put(master);
return ret;
@@ -526,8 +681,14 @@ err_free_master:
static int sun6i_spi_remove(struct platform_device *pdev)
{
+ struct spi_master *master = platform_get_drvdata(pdev);
+
pm_runtime_force_suspend(&pdev->dev);
+ if (master->dma_tx)
+ dma_release_channel(master->dma_tx);
+ if (master->dma_rx)
+ dma_release_channel(master->dma_rx);
return 0;
}
diff --git a/drivers/spi/spi-synquacer.c b/drivers/spi/spi-synquacer.c
index 42e82dbe3d41..8cdca6ab8098 100644
--- a/drivers/spi/spi-synquacer.c
+++ b/drivers/spi/spi-synquacer.c
@@ -657,7 +657,8 @@ static int synquacer_spi_probe(struct platform_device *pdev)
if (!master->max_speed_hz) {
dev_err(&pdev->dev, "missing clock source\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto disable_clk;
}
master->min_speed_hz = master->max_speed_hz / 254;
@@ -670,7 +671,7 @@ static int synquacer_spi_probe(struct platform_device *pdev)
rx_irq = platform_get_irq(pdev, 0);
if (rx_irq <= 0) {
ret = rx_irq;
- goto put_spi;
+ goto disable_clk;
}
snprintf(sspi->rx_irq_name, SYNQUACER_HSSPI_IRQ_NAME_MAX, "%s-rx",
dev_name(&pdev->dev));
@@ -678,13 +679,13 @@ static int synquacer_spi_probe(struct platform_device *pdev)
0, sspi->rx_irq_name, sspi);
if (ret) {
dev_err(&pdev->dev, "request rx_irq failed (%d)\n", ret);
- goto put_spi;
+ goto disable_clk;
}
tx_irq = platform_get_irq(pdev, 1);
if (tx_irq <= 0) {
ret = tx_irq;
- goto put_spi;
+ goto disable_clk;
}
snprintf(sspi->tx_irq_name, SYNQUACER_HSSPI_IRQ_NAME_MAX, "%s-tx",
dev_name(&pdev->dev));
@@ -692,7 +693,7 @@ static int synquacer_spi_probe(struct platform_device *pdev)
0, sspi->tx_irq_name, sspi);
if (ret) {
dev_err(&pdev->dev, "request tx_irq failed (%d)\n", ret);
- goto put_spi;
+ goto disable_clk;
}
master->dev.of_node = np;
@@ -710,7 +711,7 @@ static int synquacer_spi_probe(struct platform_device *pdev)
ret = synquacer_spi_enable(master);
if (ret)
- goto fail_enable;
+ goto disable_clk;
pm_runtime_set_active(sspi->dev);
pm_runtime_enable(sspi->dev);
@@ -723,7 +724,7 @@ static int synquacer_spi_probe(struct platform_device *pdev)
disable_pm:
pm_runtime_disable(sspi->dev);
-fail_enable:
+disable_clk:
clk_disable_unprepare(sspi->clk);
put_spi:
spi_master_put(master);
diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index ca6886aaa519..a2e5907276e7 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -966,6 +966,7 @@ static int tegra_spi_setup(struct spi_device *spi)
ret = pm_runtime_get_sync(tspi->dev);
if (ret < 0) {
+ pm_runtime_put_noidle(tspi->dev);
dev_err(tspi->dev, "pm runtime failed, e = %d\n", ret);
if (cdata)
tegra_spi_cleanup(spi);
@@ -1474,6 +1475,7 @@ static int tegra_spi_resume(struct device *dev)
ret = pm_runtime_get_sync(dev);
if (ret < 0) {
+ pm_runtime_put_noidle(dev);
dev_err(dev, "pm runtime failed, e = %d\n", ret);
return ret;
}
diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c
index b59015c7c8a8..cfb7de737937 100644
--- a/drivers/spi/spi-tegra20-sflash.c
+++ b/drivers/spi/spi-tegra20-sflash.c
@@ -552,6 +552,7 @@ static int tegra_sflash_resume(struct device *dev)
ret = pm_runtime_get_sync(dev);
if (ret < 0) {
+ pm_runtime_put_noidle(dev);
dev_err(dev, "pm runtime failed, e = %d\n", ret);
return ret;
}
diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c
index a0810765d4e5..f7c832fd4003 100644
--- a/drivers/spi/spi-tegra20-slink.c
+++ b/drivers/spi/spi-tegra20-slink.c
@@ -751,6 +751,7 @@ static int tegra_slink_setup(struct spi_device *spi)
ret = pm_runtime_get_sync(tspi->dev);
if (ret < 0) {
+ pm_runtime_put_noidle(tspi->dev);
dev_err(tspi->dev, "pm runtime failed, e = %d\n", ret);
return ret;
}
@@ -1188,6 +1189,7 @@ static int tegra_slink_resume(struct device *dev)
ret = pm_runtime_get_sync(dev);
if (ret < 0) {
+ pm_runtime_put_noidle(dev);
dev_err(dev, "pm runtime failed, e = %d\n", ret);
return ret;
}
diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c
index 3c41649698a5..9417385c0921 100644
--- a/drivers/spi/spi-ti-qspi.c
+++ b/drivers/spi/spi-ti-qspi.c
@@ -174,6 +174,7 @@ static int ti_qspi_setup(struct spi_device *spi)
ret = pm_runtime_get_sync(qspi->dev);
if (ret < 0) {
+ pm_runtime_put_noidle(qspi->dev);
dev_err(qspi->dev, "pm_runtime_get_sync() failed\n");
return ret;
}
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 0cab239d8e7f..51d7c004fbab 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -374,16 +374,7 @@ static int spi_uevent(struct device *dev, struct kobj_uevent_env *env)
return add_uevent_var(env, "MODALIAS=%s%s", SPI_MODULE_PREFIX, spi->modalias);
}
-struct bus_type spi_bus_type = {
- .name = "spi",
- .dev_groups = spi_dev_groups,
- .match = spi_match_device,
- .uevent = spi_uevent,
-};
-EXPORT_SYMBOL_GPL(spi_bus_type);
-
-
-static int spi_drv_probe(struct device *dev)
+static int spi_probe(struct device *dev)
{
const struct spi_driver *sdrv = to_spi_driver(dev->driver);
struct spi_device *spi = to_spi_device(dev);
@@ -405,31 +396,55 @@ static int spi_drv_probe(struct device *dev)
if (ret)
return ret;
- ret = sdrv->probe(spi);
- if (ret)
- dev_pm_domain_detach(dev, true);
+ if (sdrv->probe) {
+ ret = sdrv->probe(spi);
+ if (ret)
+ dev_pm_domain_detach(dev, true);
+ }
return ret;
}
-static int spi_drv_remove(struct device *dev)
+static int spi_remove(struct device *dev)
{
const struct spi_driver *sdrv = to_spi_driver(dev->driver);
- int ret;
- ret = sdrv->remove(to_spi_device(dev));
+ if (sdrv->remove) {
+ int ret;
+
+ ret = sdrv->remove(to_spi_device(dev));
+ if (ret)
+ dev_warn(dev,
+ "Failed to unbind driver (%pe), ignoring\n",
+ ERR_PTR(ret));
+ }
+
dev_pm_domain_detach(dev, true);
- return ret;
+ return 0;
}
-static void spi_drv_shutdown(struct device *dev)
+static void spi_shutdown(struct device *dev)
{
- const struct spi_driver *sdrv = to_spi_driver(dev->driver);
+ if (dev->driver) {
+ const struct spi_driver *sdrv = to_spi_driver(dev->driver);
- sdrv->shutdown(to_spi_device(dev));
+ if (sdrv->shutdown)
+ sdrv->shutdown(to_spi_device(dev));
+ }
}
+struct bus_type spi_bus_type = {
+ .name = "spi",
+ .dev_groups = spi_dev_groups,
+ .match = spi_match_device,
+ .uevent = spi_uevent,
+ .probe = spi_probe,
+ .remove = spi_remove,
+ .shutdown = spi_shutdown,
+};
+EXPORT_SYMBOL_GPL(spi_bus_type);
+
/**
* __spi_register_driver - register a SPI driver
* @owner: owner module of the driver to register
@@ -442,12 +457,6 @@ int __spi_register_driver(struct module *owner, struct spi_driver *sdrv)
{
sdrv->driver.owner = owner;
sdrv->driver.bus = &spi_bus_type;
- if (sdrv->probe)
- sdrv->driver.probe = spi_drv_probe;
- if (sdrv->remove)
- sdrv->driver.remove = spi_drv_remove;
- if (sdrv->shutdown)
- sdrv->driver.shutdown = spi_drv_shutdown;
return driver_register(&sdrv->driver);
}
EXPORT_SYMBOL_GPL(__spi_register_driver);
@@ -812,18 +821,16 @@ static void spi_set_cs(struct spi_device *spi, bool enable)
enable = !enable;
if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio)) {
- /*
- * Honour the SPI_NO_CS flag and invert the enable line, as
- * active low is default for SPI. Execution paths that handle
- * polarity inversion in gpiolib (such as device tree) will
- * enforce active high using the SPI_CS_HIGH resulting in a
- * double inversion through the code above.
- */
if (!(spi->mode & SPI_NO_CS)) {
if (spi->cs_gpiod)
+ /* polarity handled by gpiolib */
gpiod_set_value_cansleep(spi->cs_gpiod,
- !enable);
+ enable1);
else
+ /*
+ * invert the enable line, as active low is
+ * default for SPI.
+ */
gpio_set_value_cansleep(spi->cs_gpio, !enable);
}
/* Some SPI masters need both GPIO CS & slave_select */
@@ -1992,15 +1999,6 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
}
spi->chip_select = value;
- /*
- * For descriptors associated with the device, polarity inversion is
- * handled in the gpiolib, so all gpio chip selects are "active high"
- * in the logical sense, the gpiolib will invert the line if need be.
- */
- if ((ctlr->use_gpio_descriptors) && ctlr->cs_gpiods &&
- ctlr->cs_gpiods[spi->chip_select])
- spi->mode |= SPI_CS_HIGH;
-
/* Device speed */
if (!of_property_read_u32(nc, "spi-max-frequency", &value))
spi->max_speed_hz = value;
@@ -2453,6 +2451,49 @@ struct spi_controller *__spi_alloc_controller(struct device *dev,
}
EXPORT_SYMBOL_GPL(__spi_alloc_controller);
+static void devm_spi_release_controller(struct device *dev, void *ctlr)
+{
+ spi_controller_put(*(struct spi_controller **)ctlr);
+}
+
+/**
+ * __devm_spi_alloc_controller - resource-managed __spi_alloc_controller()
+ * @dev: physical device of SPI controller
+ * @size: how much zeroed driver-private data to allocate
+ * @slave: whether to allocate an SPI master (false) or SPI slave (true)
+ * Context: can sleep
+ *
+ * Allocate an SPI controller and automatically release a reference on it
+ * when @dev is unbound from its driver. Drivers are thus relieved from
+ * having to call spi_controller_put().
+ *
+ * The arguments to this function are identical to __spi_alloc_controller().
+ *
+ * Return: the SPI controller structure on success, else NULL.
+ */
+struct spi_controller *__devm_spi_alloc_controller(struct device *dev,
+ unsigned int size,
+ bool slave)
+{
+ struct spi_controller **ptr, *ctlr;
+
+ ptr = devres_alloc(devm_spi_release_controller, sizeof(*ptr),
+ GFP_KERNEL);
+ if (!ptr)
+ return NULL;
+
+ ctlr = __spi_alloc_controller(dev, size, slave);
+ if (ctlr) {
+ *ptr = ctlr;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return ctlr;
+}
+EXPORT_SYMBOL_GPL(__devm_spi_alloc_controller);
+
#ifdef CONFIG_OF
static int of_spi_get_gpio_numbers(struct spi_controller *ctlr)
{
@@ -2789,6 +2830,11 @@ int devm_spi_register_controller(struct device *dev,
}
EXPORT_SYMBOL_GPL(devm_spi_register_controller);
+static int devm_spi_match_controller(struct device *dev, void *res, void *ctlr)
+{
+ return *(struct spi_controller **)res == ctlr;
+}
+
static int __unregister(struct device *dev, void *null)
{
spi_unregister_device(to_spi_device(dev));
@@ -2830,7 +2876,15 @@ void spi_unregister_controller(struct spi_controller *ctlr)
list_del(&ctlr->list);
mutex_unlock(&board_lock);
- device_unregister(&ctlr->dev);
+ device_del(&ctlr->dev);
+
+ /* Release the last reference on the controller if its driver
+ * has not yet been converted to devm_spi_alloc_master/slave().
+ */
+ if (!devres_find(ctlr->dev.parent, devm_spi_release_controller,
+ devm_spi_match_controller, ctlr))
+ put_device(&ctlr->dev);
+
/* free bus id */
mutex_lock(&board_lock);
if (found == ctlr)
@@ -3193,9 +3247,9 @@ static int __spi_split_transfer_maxsize(struct spi_controller *ctlr,
}
/**
- * spi_split_tranfers_maxsize - split spi transfers into multiple transfers
- * when an individual transfer exceeds a
- * certain size
+ * spi_split_transfers_maxsize - split spi transfers into multiple transfers
+ * when an individual transfer exceeds a
+ * certain size
* @ctlr: the @spi_controller for this transfer
* @msg: the @spi_message to transform
* @maxsize: the maximum when to apply this
@@ -3324,15 +3378,19 @@ int spi_setup(struct spi_device *spi)
if (status)
return status;
- if (!spi->max_speed_hz)
+ if (!spi->max_speed_hz ||
+ spi->max_speed_hz > spi->controller->max_speed_hz)
spi->max_speed_hz = spi->controller->max_speed_hz;
+ mutex_lock(&spi->controller->io_mutex);
+
if (spi->controller->setup)
status = spi->controller->setup(spi);
if (spi->controller->auto_runtime_pm && spi->controller->set_cs) {
status = pm_runtime_get_sync(spi->controller->dev.parent);
if (status < 0) {
+ mutex_unlock(&spi->controller->io_mutex);
pm_runtime_put_noidle(spi->controller->dev.parent);
dev_err(&spi->controller->dev, "Failed to power device: %d\n",
status);
@@ -3354,6 +3412,8 @@ int spi_setup(struct spi_device *spi)
spi_set_cs(spi, false);
}
+ mutex_unlock(&spi->controller->io_mutex);
+
if (spi->rt && !spi->controller->rt) {
spi->controller->rt = true;
spi_set_thread_rt(spi->controller);