diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-04-16 00:34:11 +0300 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-04-16 00:34:11 +0300 |
| commit | 405f6584d7d0fc46534fd370e374630283dffe60 (patch) | |
| tree | 3fb3b28d26578f450f446bedc2818a6fc26101f0 | |
| parent | 44f7a3795395b54bf674002803e3e80c6312e210 (diff) | |
| parent | c4c3fc872d2a05bf10372233c98e81344e685cdf (diff) | |
| download | linux-405f6584d7d0fc46534fd370e374630283dffe60.tar.xz | |
Merge tag 'spi-v7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi updates from Mark Brown:
"A busy release for SPI, almost all of it in a couple of larger fix and
cleanup series for patterns that affected many drivers. We do have a
couple of core API additions as well, relatively application specific
but they enable some new use cases.
- A packed command operation for spi-mem devices
- Improvements to the ancillary device support to enable some IIO use
cases from Antoniu Miclaus
- Fixes for a registration ordering issue pattern caused by the
handover between allocation and registration of controllers in
concert with devm from Johan Hovold
- Improvements to handling of clock allocation from Pei Xiao
- Cleanups in the fsl-lpspi driver from Marc Kleine-Budde
- Support for Renesas RZ/G3E and RZ/G3L"
* tag 'spi-v7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (115 commits)
spi: sn-f-ospi: fix incorrect return code for invalid num-cs
spi: spi-mem: Add a packed command operation
spi: cadence-qspi: Revert the filtering of certain opcodes in ODTR
spi: mtk-snfi: unregister ECC engine on probe failure and remove() callback
spi: s3c64xx: fix NULL-deref on driver unbind
spi: zynq-qspi: fix controller deregistration
spi: zynqmp-gqspi: fix controller deregistration
spi: uniphier: fix controller deregistration
spi: ti-qspi: fix controller deregistration
spi: tegra20-sflash: fix controller deregistration
spi: tegra114: fix controller deregistration
spi: syncuacer: fix controller deregistration
spi: sun6i: fix controller deregistration
spi: sun4i: fix controller deregistration
spi: st-ssc4: fix controller deregistration
spi: sprd: fix controller deregistration
spi: slave-mt27xx: fix controller deregistration
spi: sifive: fix controller deregistration
spi: sh-msiof: fix controller deregistration
spi: sh-hspi: fix controller deregistration
...
75 files changed, 741 insertions, 493 deletions
diff --git a/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml b/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml index 636338d24bdf..8ff50dfcf585 100644 --- a/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml +++ b/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml @@ -35,10 +35,10 @@ properties: interrupts: maxItems: 1 - clock-names: + clocks: maxItems: 1 - clocks: + resets: maxItems: 1 microchip,apb-datawidth: diff --git a/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml b/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml index a588b112e11e..f40f316943ba 100644 --- a/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml +++ b/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml @@ -13,10 +13,13 @@ properties: compatible: oneOf: - enum: + - renesas,r9a08g046-rspi # RZ/G3L - renesas,r9a09g057-rspi # RZ/V2H(P) - renesas,r9a09g077-rspi # RZ/T2H - items: - - const: renesas,r9a09g056-rspi # RZ/V2N + - enum: + - renesas,r9a09g047-rspi # RZ/G3E + - renesas,r9a09g056-rspi # RZ/V2N - const: renesas,r9a09g057-rspi - items: - const: renesas,r9a09g087-rspi # RZ/N2H @@ -58,12 +61,19 @@ properties: - const: tresetn dmas: - maxItems: 2 + minItems: 2 + maxItems: 10 + description: + Must contain a list of pairs of references to DMA specifiers, one for + transmission, and one for reception. dma-names: + minItems: 2 + maxItems: 10 items: - - const: rx - - const: tx + enum: + - rx + - tx power-domains: maxItems: 1 @@ -86,6 +96,34 @@ allOf: compatible: contains: enum: + - renesas,r9a08g046-rspi + then: + properties: + clocks: + maxItems: 2 + + clock-names: + items: + - const: pclk + - const: tclk + + dmas: + maxItems: 2 + + dma-names: + items: + - const: rx + - const: tx + + required: + - resets + - reset-names + + - if: + properties: + compatible: + contains: + enum: - renesas,r9a09g057-rspi then: properties: @@ -121,6 +159,12 @@ allOf: resets: false reset-names: false + dmas: + maxItems: 6 + + dma-names: + maxItems: 6 + unevaluatedProperties: false examples: diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index c3b2f02f5912..b563f49e2197 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -138,7 +138,7 @@ config SPI_AR934X config SPI_ATCSPI200 tristate "Andes ATCSPI200 SPI controller" - depends on ARCH_ANDES + depends on ARCH_ANDES || COMPILE_TEST help SPI driver for Andes ATCSPI200 SPI controller. ATCSPI200 controller supports DMA and PIO modes. When DMA @@ -866,7 +866,7 @@ config SPI_PIC32_SQI config SPI_PL022 tristate "ARM AMBA PL022 SSP controller" - depends on ARM_AMBA + depends on ARM_AMBA || COMPILE_TEST default y if ARCH_REALVIEW default y if INTEGRATOR_IMPD1 default y if ARCH_VERSATILE diff --git a/drivers/spi/spi-amlogic-spisg.c b/drivers/spi/spi-amlogic-spisg.c index 9d568e385f05..19c5eba412ef 100644 --- a/drivers/spi/spi-amlogic-spisg.c +++ b/drivers/spi/spi-amlogic-spisg.c @@ -647,13 +647,13 @@ static int aml_spisg_clk_init(struct spisg_device *spisg, void __iomem *base) int ret, i; spisg->core = devm_clk_get_enabled(dev, "core"); - if (IS_ERR_OR_NULL(spisg->core)) { + if (IS_ERR(spisg->core)) { dev_err(dev, "core clock request failed\n"); return PTR_ERR(spisg->core); } spisg->pclk = devm_clk_get_enabled(dev, "pclk"); - if (IS_ERR_OR_NULL(spisg->pclk)) { + if (IS_ERR(spisg->pclk)) { dev_err(dev, "pclk clock request failed\n"); return PTR_ERR(spisg->pclk); } @@ -703,7 +703,7 @@ static int aml_spisg_clk_init(struct spisg_device *spisg, void __iomem *base) } spisg->sclk = devm_clk_hw_get_clk(dev, &div->hw, NULL); - if (IS_ERR_OR_NULL(spisg->sclk)) { + if (IS_ERR(spisg->sclk)) { dev_err(dev, "get clock failed\n"); return PTR_ERR(spisg->sclk); } @@ -800,7 +800,7 @@ static int aml_spisg_probe(struct platform_device *pdev) goto out_clk; } - ret = devm_spi_register_controller(dev, ctlr); + ret = spi_register_controller(ctlr); if (ret) { dev_err(&pdev->dev, "spi controller registration failed\n"); goto out_clk; @@ -823,6 +823,8 @@ static void aml_spisg_remove(struct platform_device *pdev) { struct spisg_device *spisg = platform_get_drvdata(pdev); + spi_unregister_controller(spisg->controller); + if (!pm_runtime_suspended(&pdev->dev)) { pinctrl_pm_select_sleep_state(&spisg->pdev->dev); clk_disable_unprepare(spisg->core); diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c index 9c286e534bf0..c21323e07d3c 100644 --- a/drivers/spi/spi-aspeed-smc.c +++ b/drivers/spi/spi-aspeed-smc.c @@ -972,7 +972,7 @@ static int aspeed_spi_probe(struct platform_device *pdev) return -ENOMEM; aspi = spi_controller_get_devdata(ctlr); - platform_set_drvdata(pdev, aspi); + platform_set_drvdata(pdev, ctlr); aspi->data = data; aspi->dev = dev; @@ -1021,7 +1021,7 @@ static int aspeed_spi_probe(struct platform_device *pdev) return ret; } - ret = devm_spi_register_controller(dev, ctlr); + ret = spi_register_controller(ctlr); if (ret) dev_err(&pdev->dev, "spi_register_controller failed\n"); @@ -1030,7 +1030,10 @@ static int aspeed_spi_probe(struct platform_device *pdev) static void aspeed_spi_remove(struct platform_device *pdev) { - struct aspeed_spi *aspi = platform_get_drvdata(pdev); + struct spi_controller *ctlr = platform_get_drvdata(pdev); + struct aspeed_spi *aspi = spi_controller_get_devdata(ctlr); + + spi_unregister_controller(ctlr); aspeed_spi_enable(aspi, false); } diff --git a/drivers/spi/spi-at91-usart.c b/drivers/spi/spi-at91-usart.c index 76eb3ba75ab1..79edc1cd13c0 100644 --- a/drivers/spi/spi-at91-usart.c +++ b/drivers/spi/spi-at91-usart.c @@ -556,7 +556,7 @@ static int at91_usart_spi_probe(struct platform_device *pdev) spin_lock_init(&aus->lock); init_completion(&aus->xfer_completion); - ret = devm_spi_register_controller(&pdev->dev, controller); + ret = spi_register_controller(controller); if (ret) goto at91_usart_fail_register_controller; @@ -634,8 +634,14 @@ static void at91_usart_spi_remove(struct platform_device *pdev) struct spi_controller *ctlr = platform_get_drvdata(pdev); struct at91_usart_spi *aus = spi_controller_get_devdata(ctlr); + spi_controller_get(ctlr); + + spi_unregister_controller(ctlr); + at91_usart_spi_release_dma(ctlr); clk_disable_unprepare(aus->clk); + + spi_controller_put(ctlr); } static const struct dev_pm_ops at91_usart_spi_pm_ops = { diff --git a/drivers/spi/spi-atcspi200.c b/drivers/spi/spi-atcspi200.c index 2665f31a49ce..3832d9db3cbf 100644 --- a/drivers/spi/spi-atcspi200.c +++ b/drivers/spi/spi-atcspi200.c @@ -494,11 +494,6 @@ static int atcspi_init_resources(struct platform_device *pdev, return dev_err_probe(spi->dev, PTR_ERR(spi->regmap), "Failed to init regmap\n"); - spi->clk = devm_clk_get(spi->dev, NULL); - if (IS_ERR(spi->clk)) - return dev_err_probe(spi->dev, PTR_ERR(spi->clk), - "Failed to get SPI clock\n"); - spi->sclk_rate = ATCSPI_MAX_SPEED_HZ; return 0; } @@ -520,13 +515,10 @@ static int atcspi_configure_dma(struct atcspi_dev *spi) static int atcspi_enable_clk(struct atcspi_dev *spi) { - int ret; - - ret = clk_prepare_enable(spi->clk); - if (ret) - return dev_err_probe(spi->dev, ret, - "Failed to enable clock\n"); - + spi->clk = devm_clk_get_enabled(spi->dev, NULL); + if (IS_ERR(spi->clk)) + return dev_err_probe(spi->dev, PTR_ERR(spi->clk), + "Failed to get SPI clock\n"); spi->clk_rate = clk_get_rate(spi->clk); if (!spi->clk_rate) return dev_err_probe(spi->dev, -EINVAL, @@ -567,6 +559,8 @@ static int atcspi_probe(struct platform_device *pdev) spi->dev = &pdev->dev; dev_set_drvdata(&pdev->dev, host); + mutex_init(&spi->mutex_lock); + ret = atcspi_init_resources(pdev, spi, &mem_res); if (ret) goto free_controller; @@ -579,15 +573,14 @@ static int atcspi_probe(struct platform_device *pdev) ret = atcspi_setup(spi); if (ret) - goto disable_clk; + goto free_controller; ret = devm_spi_register_controller(&pdev->dev, host); if (ret) { dev_err_probe(spi->dev, ret, "Failed to register SPI controller\n"); - goto disable_clk; + goto free_controller; } - spi->use_dma = false; if (ATCSPI_DMA_SUPPORT) { ret = atcspi_configure_dma(spi); @@ -597,14 +590,11 @@ static int atcspi_probe(struct platform_device *pdev) else spi->use_dma = true; } - mutex_init(&spi->mutex_lock); return 0; -disable_clk: - clk_disable_unprepare(spi->clk); - free_controller: + mutex_destroy(&spi->mutex_lock); spi_controller_put(host); return ret; } @@ -661,7 +651,6 @@ static struct platform_driver atcspi_driver = { .probe = atcspi_probe, .driver = { .name = "atcspi200", - .owner = THIS_MODULE, .of_match_table = atcspi_of_match, .pm = pm_sleep_ptr(&atcspi_pm_ops) } diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 445d645585bf..42db85d7ff8e 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1654,7 +1654,7 @@ static int atmel_spi_probe(struct platform_device *pdev) pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) goto out_free_dma; @@ -1688,8 +1688,12 @@ static void atmel_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct atmel_spi *as = spi_controller_get_devdata(host); + spi_controller_get(host); + pm_runtime_get_sync(&pdev->dev); + spi_unregister_controller(host); + /* reset the hardware and block queue progress */ if (as->use_dma) { atmel_spi_stop_dma(host); @@ -1716,6 +1720,8 @@ static void atmel_spi_remove(struct platform_device *pdev) pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + + spi_controller_put(host); } static int atmel_spi_runtime_suspend(struct device *dev) diff --git a/drivers/spi/spi-axiado.c b/drivers/spi/spi-axiado.c index 8ddcd27def22..dc55c55ae63c 100644 --- a/drivers/spi/spi-axiado.c +++ b/drivers/spi/spi-axiado.c @@ -842,7 +842,6 @@ static int ax_spi_probe(struct platform_device *pdev) ctlr->bits_per_word_mask = SPI_BPW_MASK(8); - pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_put_autosuspend(&pdev->dev); ctlr->mem_ops = &ax_spi_mem_ops; diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index 612f8802e690..e935e8ab9cfd 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -758,8 +758,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) if (IS_ERR(regs)) return PTR_ERR(regs); - clk = devm_clk_get(dev, "hsspi"); - + clk = devm_clk_get_enabled(dev, "hsspi"); if (IS_ERR(clk)) return PTR_ERR(clk); @@ -767,41 +766,26 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) if (IS_ERR(reset)) return PTR_ERR(reset); - ret = clk_prepare_enable(clk); - if (ret) - return ret; - ret = reset_control_reset(reset); - if (ret) { - dev_err(dev, "unable to reset device: %d\n", ret); - goto out_disable_clk; - } + if (ret) + return dev_err_probe(dev, ret, "unable to reset device: %d\n", ret); rate = clk_get_rate(clk); if (!rate) { - pll_clk = devm_clk_get(dev, "pll"); - - if (IS_ERR(pll_clk)) { - ret = PTR_ERR(pll_clk); - goto out_disable_clk; - } - - ret = clk_prepare_enable(pll_clk); - if (ret) - goto out_disable_clk; + pll_clk = devm_clk_get_enabled(dev, "pll"); + if (IS_ERR(pll_clk)) + return dev_err_probe(dev, PTR_ERR(pll_clk), + "failed enable pll clk\n"); rate = clk_get_rate(pll_clk); - if (!rate) { - ret = -EINVAL; - goto out_disable_pll_clk; - } + if (!rate) + return dev_err_probe(dev, -EINVAL, + "failed get pll clk rate\n"); } host = spi_alloc_host(&pdev->dev, sizeof(*bs)); - if (!host) { - ret = -ENOMEM; - goto out_disable_pll_clk; - } + if (!host) + return dev_err_probe(dev, -ENOMEM, "alloc host no mem\n"); bs = spi_controller_get_devdata(host); bs->pdev = pdev; @@ -873,7 +857,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) } /* register and we are done */ - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) goto out_sysgroup_disable; @@ -887,10 +871,6 @@ out_pm_disable: pm_runtime_disable(&pdev->dev); out_put_host: spi_controller_put(host); -out_disable_pll_clk: - clk_disable_unprepare(pll_clk); -out_disable_clk: - clk_disable_unprepare(clk); return ret; } @@ -900,11 +880,15 @@ static void bcm63xx_hsspi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + /* reset the hardware and block queue progress */ __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); - clk_disable_unprepare(bs->pll_clk); - clk_disable_unprepare(bs->clk); sysfs_remove_group(&pdev->dev.kobj, &bcm63xx_hsspi_group); + + spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 47266bb23a33..40cd7efc4b54 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -602,7 +602,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) goto out_clk_disable; /* register and we are done */ - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(dev, "spi register failed\n"); goto out_clk_disable; @@ -625,11 +625,17 @@ static void bcm63xx_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct bcm63xx_spi *bs = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + /* reset spi block */ bcm_spi_writeb(bs, 0, SPI_INT_MASK); /* HW shutdown */ clk_disable_unprepare(bs->clk); + + spi_controller_put(host); } static int bcm63xx_spi_suspend(struct device *dev) diff --git a/drivers/spi/spi-bcmbca-hsspi.c b/drivers/spi/spi-bcmbca-hsspi.c index ece22260f570..09c1472ae4fa 100644 --- a/drivers/spi/spi-bcmbca-hsspi.c +++ b/drivers/spi/spi-bcmbca-hsspi.c @@ -452,39 +452,30 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev) if (IS_ERR(spim_ctrl)) return PTR_ERR(spim_ctrl); - clk = devm_clk_get(dev, "hsspi"); + clk = devm_clk_get_enabled(dev, "hsspi"); if (IS_ERR(clk)) - return PTR_ERR(clk); - - ret = clk_prepare_enable(clk); - if (ret) - return ret; + return dev_err_probe(dev, PTR_ERR(clk), + "Failed to get hsspi clock\n"); rate = clk_get_rate(clk); if (!rate) { - pll_clk = devm_clk_get(dev, "pll"); + pll_clk = devm_clk_get_enabled(dev, "pll"); if (IS_ERR(pll_clk)) { - ret = PTR_ERR(pll_clk); - goto out_disable_clk; + return dev_err_probe(dev, PTR_ERR(pll_clk), + "Failed to get pll clock\n"); } - ret = clk_prepare_enable(pll_clk); - if (ret) - goto out_disable_clk; - rate = clk_get_rate(pll_clk); - if (!rate) { - ret = -EINVAL; - goto out_disable_pll_clk; - } + if (!rate) + return dev_err_probe(dev, -EINVAL, + "Failed to get pll clock rate\n"); } host = devm_spi_alloc_host(&pdev->dev, sizeof(*bs)); - if (!host) { - ret = -ENOMEM; - goto out_disable_pll_clk; - } + if (!host) + return dev_err_probe(dev, -ENOMEM, + "Failed alloc spi host\n"); bs = spi_controller_get_devdata(host); bs->pdev = pdev; @@ -535,21 +526,19 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev) ret = devm_request_irq(dev, irq, bcmbca_hsspi_interrupt, IRQF_SHARED, pdev->name, bs); if (ret) - goto out_disable_pll_clk; + return dev_err_probe(dev, ret, "Failed request irq\n"); } ret = devm_pm_runtime_enable(&pdev->dev); if (ret) - goto out_disable_pll_clk; + return dev_err_probe(dev, ret, "Failed pm runtime enable\n"); ret = sysfs_create_group(&pdev->dev.kobj, &bcmbca_hsspi_group); - if (ret) { - dev_err(&pdev->dev, "couldn't register sysfs group\n"); - goto out_disable_pll_clk; - } + if (ret) + return dev_err_probe(dev, ret, "couldn't register sysfs group\n"); /* register and we are done */ - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) goto out_sysgroup_disable; @@ -559,10 +548,6 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev) out_sysgroup_disable: sysfs_remove_group(&pdev->dev.kobj, &bcmbca_hsspi_group); -out_disable_pll_clk: - clk_disable_unprepare(pll_clk); -out_disable_clk: - clk_disable_unprepare(clk); return ret; } @@ -571,10 +556,10 @@ static void bcmbca_hsspi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct bcmbca_hsspi *bs = spi_controller_get_devdata(host); + spi_unregister_controller(host); + /* reset the hardware and block queue progress */ __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); - clk_disable_unprepare(bs->pll_clk); - clk_disable_unprepare(bs->clk); sysfs_remove_group(&pdev->dev.kobj, &bcmbca_hsspi_group); } diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index 2ead419e896e..b6f7f95e8bd3 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -1544,10 +1544,6 @@ static bool cqspi_supports_mem_op(struct spi_mem *mem, if (op->data.nbytes && op->data.buswidth != 8) return false; - /* A single opcode is supported, it will be repeated */ - if ((op->cmd.opcode >> 8) != (op->cmd.opcode & 0xFF)) - return false; - if (cqspi->is_rzn1) return false; } else if (!all_false) { diff --git a/drivers/spi/spi-cavium-octeon.c b/drivers/spi/spi-cavium-octeon.c index 155085a053a1..b95bfa6a3013 100644 --- a/drivers/spi/spi-cavium-octeon.c +++ b/drivers/spi/spi-cavium-octeon.c @@ -54,7 +54,7 @@ static int octeon_spi_probe(struct platform_device *pdev) host->bits_per_word_mask = SPI_BPW_MASK(8); host->max_speed_hz = OCTEON_SPI_MAX_CLOCK_HZ; - err = devm_spi_register_controller(&pdev->dev, host); + err = spi_register_controller(host); if (err) { dev_err(&pdev->dev, "register host failed: %d\n", err); goto fail; @@ -73,8 +73,14 @@ static void octeon_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct octeon_spi *p = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + /* Clear the CSENA* and put everything in a known state. */ writeq(0, p->register_base + OCTEON_SPI_CFG(p)); + + spi_controller_put(host); } static const struct of_device_id octeon_spi_match[] = { diff --git a/drivers/spi/spi-cavium-thunderx.c b/drivers/spi/spi-cavium-thunderx.c index 99aac40a1bba..f1a9aa696c87 100644 --- a/drivers/spi/spi-cavium-thunderx.c +++ b/drivers/spi/spi-cavium-thunderx.c @@ -70,7 +70,7 @@ static int thunderx_spi_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, host); - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) goto error; @@ -90,8 +90,14 @@ static void thunderx_spi_remove(struct pci_dev *pdev) if (!p) return; + spi_controller_get(host); + + spi_unregister_controller(host); + /* Put everything in a known state. */ writeq(0, p->register_base + OCTEON_SPI_CFG(p)); + + spi_controller_put(host); } static const struct pci_device_id thunderx_spi_pci_id_table[] = { diff --git a/drivers/spi/spi-ch341.c b/drivers/spi/spi-ch341.c index 79d2f9ab4ef0..3eaa8f176f63 100644 --- a/drivers/spi/spi-ch341.c +++ b/drivers/spi/spi-ch341.c @@ -152,7 +152,7 @@ static int ch341_probe(struct usb_interface *intf, if (ret) return ret; - ctrl = devm_spi_alloc_host(&udev->dev, sizeof(struct ch341_spi_dev)); + ctrl = devm_spi_alloc_host(&intf->dev, sizeof(struct ch341_spi_dev)); if (!ctrl) return -ENOMEM; @@ -163,7 +163,7 @@ static int ch341_probe(struct usb_interface *intf, ch341->read_pipe = usb_rcvbulkpipe(udev, usb_endpoint_num(in)); ch341->rx_len = usb_endpoint_maxp(in); - ch341->rx_buf = devm_kzalloc(&udev->dev, ch341->rx_len, GFP_KERNEL); + ch341->rx_buf = devm_kzalloc(&intf->dev, ch341->rx_len, GFP_KERNEL); if (!ch341->rx_buf) return -ENOMEM; @@ -171,19 +171,18 @@ static int ch341_probe(struct usb_interface *intf, if (!ch341->rx_urb) return -ENOMEM; - ch341->tx_buf = - devm_kzalloc(&udev->dev, CH341_PACKET_LENGTH, GFP_KERNEL); - if (!ch341->tx_buf) - return -ENOMEM; + ch341->tx_buf = devm_kzalloc(&intf->dev, CH341_PACKET_LENGTH, GFP_KERNEL); + if (!ch341->tx_buf) { + ret = -ENOMEM; + goto err_free_urb; + } usb_fill_bulk_urb(ch341->rx_urb, udev, ch341->read_pipe, ch341->rx_buf, ch341->rx_len, ch341_recv, ch341); ret = usb_submit_urb(ch341->rx_urb, GFP_KERNEL); - if (ret) { - usb_free_urb(ch341->rx_urb); - return -ENOMEM; - } + if (ret) + goto err_free_urb; ctrl->bus_num = -1; ctrl->mode_bits = SPI_CPHA; @@ -195,21 +194,34 @@ static int ch341_probe(struct usb_interface *intf, ret = ch341_config_stream(ch341); if (ret) - return ret; + goto err_kill_urb; ret = ch341_enable_pins(ch341, true); if (ret) - return ret; + goto err_kill_urb; ret = spi_register_controller(ctrl); if (ret) - return ret; + goto err_disable_pins; ch341->spidev = spi_new_device(ctrl, &chip); - if (!ch341->spidev) - return -ENOMEM; + if (!ch341->spidev) { + ret = -ENOMEM; + goto err_unregister; + } return 0; + +err_unregister: + spi_unregister_controller(ctrl); +err_disable_pins: + ch341_enable_pins(ch341, false); +err_kill_urb: + usb_kill_urb(ch341->rx_urb); +err_free_urb: + usb_free_urb(ch341->rx_urb); + + return ret; } static void ch341_disconnect(struct usb_interface *intf) @@ -219,6 +231,7 @@ static void ch341_disconnect(struct usb_interface *intf) spi_unregister_device(ch341->spidev); spi_unregister_controller(ch341->ctrl); ch341_enable_pins(ch341, false); + usb_kill_urb(ch341->rx_urb); usb_free_urb(ch341->rx_urb); } diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index fdf37636cb9f..b45f44de85dc 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -410,9 +410,9 @@ static int mcfqspi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, host); pm_runtime_enable(&pdev->dev); - status = devm_spi_register_controller(&pdev->dev, host); + status = spi_register_controller(host); if (status) { - dev_dbg(&pdev->dev, "devm_spi_register_controller failed\n"); + dev_dbg(&pdev->dev, "failed to register controller\n"); goto fail1; } @@ -436,11 +436,17 @@ static void mcfqspi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct mcfqspi *mcfqspi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_disable(&pdev->dev); /* disable the hardware (set the baud rate to 0) */ mcfqspi_wr_qmr(mcfqspi, MCFQSPI_QMR_MSTR); mcfqspi_cs_teardown(mcfqspi); + + spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/spi-cs42l43.c b/drivers/spi/spi-cs42l43.c index a4a650c8d740..68f208ef1e01 100644 --- a/drivers/spi/spi-cs42l43.c +++ b/drivers/spi/spi-cs42l43.c @@ -367,10 +367,10 @@ static int cs42l43_spi_probe(struct platform_device *pdev) ret = devm_add_action_or_reset(priv->dev, cs42l43_release_of_node, fwnode); if (ret) return ret; + } else { + fwnode_property_read_u32(xu_fwnode, "01fa-sidecar-instances", &nsidecars); } - fwnode_property_read_u32(xu_fwnode, "01fa-sidecar-instances", &nsidecars); - /* * Depending on the value of nsidecars we either create a software node * or assign an fwnode. We don't want software node to be attached to diff --git a/drivers/spi/spi-dln2.c b/drivers/spi/spi-dln2.c index d90282960ab6..392f0d05f508 100644 --- a/drivers/spi/spi-dln2.c +++ b/drivers/spi/spi-dln2.c @@ -758,7 +758,7 @@ static int dln2_spi_probe(struct platform_device *pdev) pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret < 0) { dev_err(&pdev->dev, "Failed to register host\n"); goto exit_register; @@ -783,10 +783,16 @@ static void dln2_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct dln2_spi *dln2 = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_disable(&pdev->dev); if (dln2_spi_enable(dln2, false) < 0) dev_err(&pdev->dev, "Failed to disable SPI module\n"); + + spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 90d5f3ea6508..db50018050e5 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -689,7 +689,7 @@ static int ep93xx_spi_probe(struct platform_device *pdev) /* make sure that the hardware is disabled */ writel(0, espi->mmio + SSPCR1); - error = devm_spi_register_controller(&pdev->dev, host); + error = spi_register_controller(host); if (error) { dev_err(&pdev->dev, "failed to register SPI host\n"); goto fail_free_dma; @@ -713,7 +713,13 @@ static void ep93xx_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct ep93xx_spi *espi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + ep93xx_spi_release_dma(espi); + + spi_controller_put(host); } static const struct of_device_id ep93xx_spi_of_ids[] = { diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 56270f8fdc17..45b9974ae911 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -718,7 +718,7 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem, pm_runtime_enable(dev); pm_runtime_get_sync(dev); - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret < 0) goto err_pm; @@ -782,7 +782,15 @@ static int of_fsl_espi_probe(struct platform_device *ofdev) static void of_fsl_espi_remove(struct platform_device *dev) { + struct spi_controller *host = platform_get_drvdata(dev); + + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_disable(&dev->dev); + + spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index 45390e9b8cae..e201309f8aae 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -75,14 +75,20 @@ #define CFGR1_PCSPOL_MASK GENMASK(11, 8) #define CFGR1_NOSTALL BIT(3) #define CFGR1_HOST BIT(0) +#define FCR_RXWATER GENMASK(18, 16) +#define FCR_TXWATER GENMASK(2, 0) #define FSR_TXCOUNT (0xFF) #define RSR_RXEMPTY BIT(1) #define TCR_CPOL BIT(31) #define TCR_CPHA BIT(30) +#define TCR_MODE GENMASK(31, 30) +#define TCR_PRESCALE GENMASK(29, 27) +#define TCR_PCS GENMASK(25, 24) #define TCR_CONT BIT(21) #define TCR_CONTC BIT(20) #define TCR_RXMSK BIT(19) #define TCR_TXMSK BIT(18) +#define TCR_FRAMESZ GENMASK(11, 0) #define SR_CLEAR_MASK GENMASK(13, 8) @@ -95,7 +101,7 @@ struct lpspi_config { u8 bpw; u8 chip_select; u8 prescale; - u16 mode; + u32 mode; u32 speed_hz; u32 effective_speed_hz; }; @@ -112,8 +118,8 @@ struct fsl_lpspi_data { void *rx_buf; const void *tx_buf; - void (*tx)(struct fsl_lpspi_data *); - void (*rx)(struct fsl_lpspi_data *); + void (*tx)(struct fsl_lpspi_data *fsl_lpspi); + void (*rx)(struct fsl_lpspi_data *fsl_lpspi); u32 remain; u8 watermark; @@ -256,9 +262,7 @@ static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi) txfifo_cnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff; - while (txfifo_cnt < fsl_lpspi->txfifosize) { - if (!fsl_lpspi->remain) - break; + while (txfifo_cnt < fsl_lpspi->txfifosize && fsl_lpspi->remain) { fsl_lpspi->tx(fsl_lpspi); txfifo_cnt++; } @@ -271,8 +275,9 @@ static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi) } fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE); - } else + } else { fsl_lpspi_intctrl(fsl_lpspi, IER_TDIE); + } } static void fsl_lpspi_read_rx_fifo(struct fsl_lpspi_data *fsl_lpspi) @@ -281,16 +286,14 @@ static void fsl_lpspi_read_rx_fifo(struct fsl_lpspi_data *fsl_lpspi) fsl_lpspi->rx(fsl_lpspi); } -static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi, - struct spi_device *spi) +static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi) { u32 temp = 0; - temp |= fsl_lpspi->config.bpw - 1; - temp |= (fsl_lpspi->config.mode & 0x3) << 30; - temp |= (fsl_lpspi->config.chip_select & 0x3) << 24; + temp |= FIELD_PREP(TCR_FRAMESZ, fsl_lpspi->config.bpw - 1); + temp |= FIELD_PREP(TCR_PCS, fsl_lpspi->config.chip_select); if (!fsl_lpspi->is_target) { - temp |= fsl_lpspi->config.prescale << 27; + temp |= FIELD_PREP(TCR_PRESCALE, fsl_lpspi->config.prescale); /* * Set TCR_CONT will keep SS asserted after current transfer. * For the first transfer, clear TCR_CONTC to assert SS. @@ -305,10 +308,10 @@ static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi, } } - if (spi->mode & SPI_CPOL) + if (fsl_lpspi->config.mode & SPI_CPOL) temp |= TCR_CPOL; - if (spi->mode & SPI_CPHA) + if (fsl_lpspi->config.mode & SPI_CPHA) temp |= TCR_CPHA; writel(temp, fsl_lpspi->base + IMX7ULP_TCR); @@ -318,17 +321,18 @@ static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi, static void fsl_lpspi_set_watermark(struct fsl_lpspi_data *fsl_lpspi) { + u8 watermark = fsl_lpspi->watermark >> 1; u32 temp; if (!fsl_lpspi->usedma) - temp = fsl_lpspi->watermark >> 1 | - (fsl_lpspi->watermark >> 1) << 16; + temp = FIELD_PREP(FCR_TXWATER, watermark) | + FIELD_PREP(FCR_RXWATER, watermark); else - temp = fsl_lpspi->watermark >> 1; + temp = FIELD_PREP(FCR_TXWATER, watermark); writel(temp, fsl_lpspi->base + IMX7ULP_FCR); - dev_dbg(fsl_lpspi->dev, "FCR=0x%x\n", temp); + dev_dbg(fsl_lpspi->dev, "FCR=0x%08x\n", temp); } static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi) @@ -348,11 +352,10 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi) return -EINVAL; } - if (config.speed_hz > perclk_rate / 2) { + if (config.speed_hz > perclk_rate / 2) div = 2; - } else { + else div = DIV_ROUND_UP(perclk_rate, config.speed_hz); - } for (prescale = 0; prescale <= prescale_max; prescale++) { scldiv = div / (1 << prescale) - 2; @@ -466,9 +469,6 @@ static int fsl_lpspi_setup_transfer(struct spi_controller *controller, struct fsl_lpspi_data *fsl_lpspi = spi_controller_get_devdata(spi->controller); - if (t == NULL) - return -EINVAL; - fsl_lpspi->config.mode = spi->mode; fsl_lpspi->config.bpw = t->bits_per_word; fsl_lpspi->config.speed_hz = t->speed_hz; @@ -517,15 +517,12 @@ static int fsl_lpspi_prepare_message(struct spi_controller *controller, fsl_lpspi->usedma = false; ret = fsl_lpspi_setup_transfer(controller, spi, t); - if (fsl_lpspi_can_dma(controller, spi, t)) - fsl_lpspi->usedma = true; - else - fsl_lpspi->usedma = false; + fsl_lpspi->usedma = fsl_lpspi_can_dma(controller, spi, t); if (ret < 0) return ret; - fsl_lpspi_set_cmd(fsl_lpspi, spi); + fsl_lpspi_set_cmd(fsl_lpspi); /* No IRQs */ writel(0, fsl_lpspi->base + IMX7ULP_IER); @@ -574,7 +571,7 @@ static int fsl_lpspi_wait_for_completion(struct spi_controller *controller) return 0; } -static int fsl_lpspi_reset(struct fsl_lpspi_data *fsl_lpspi) +static void fsl_lpspi_reset(struct fsl_lpspi_data *fsl_lpspi) { u32 temp; @@ -589,8 +586,6 @@ static int fsl_lpspi_reset(struct fsl_lpspi_data *fsl_lpspi) /* W1C for all flags in SR */ writel(SR_CLEAR_MASK, fsl_lpspi->base + IMX7ULP_SR); - - return 0; } static void fsl_lpspi_dma_rx_callback(void *cookie) @@ -794,10 +789,7 @@ static int fsl_lpspi_transfer_one(struct spi_controller *controller, spi_controller_get_devdata(controller); int ret; - if (fsl_lpspi_can_dma(controller, spi, t)) - fsl_lpspi->usedma = true; - else - fsl_lpspi->usedma = false; + fsl_lpspi->usedma = fsl_lpspi_can_dma(controller, spi, t); ret = fsl_lpspi_setup_transfer(controller, spi, t); if (ret < 0) @@ -805,7 +797,7 @@ static int fsl_lpspi_transfer_one(struct spi_controller *controller, t->effective_speed_hz = fsl_lpspi->config.effective_speed_hz; - fsl_lpspi_set_cmd(fsl_lpspi, spi); + fsl_lpspi_set_cmd(fsl_lpspi); fsl_lpspi->is_first_byte = false; if (fsl_lpspi->usedma) diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c index a223b4bc6e63..57358851029b 100644 --- a/drivers/spi/spi-fsl-qspi.c +++ b/drivers/spi/spi-fsl-qspi.c @@ -633,7 +633,7 @@ static int fsl_qspi_do_op(struct fsl_qspi *q, const struct spi_mem_op *op) void __iomem *base = q->iobase; int err = 0; - init_completion(&q->c); + reinit_completion(&q->c); /* * Always start the sequence at the same index since we update @@ -965,6 +965,7 @@ static int fsl_qspi_probe(struct platform_device *pdev) if (ret < 0) return ret; + init_completion(&q->c); ret = devm_request_irq(dev, ret, fsl_qspi_irq_handler, 0, pdev->name, q); if (ret) { diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index bf3fc3ce0cc2..1252c41c206f 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -614,7 +614,7 @@ static struct spi_controller *fsl_spi_probe(struct device *dev, mpc8xxx_spi_write_reg(®_base->mode, regval); - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret < 0) goto err_probe; @@ -705,7 +705,13 @@ static void of_fsl_spi_remove(struct platform_device *ofdev) struct spi_controller *host = platform_get_drvdata(ofdev); struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + fsl_spi_cpm_free(mpc8xxx_spi); + + spi_controller_put(host); } static struct platform_driver of_fsl_spi_driver = { @@ -751,7 +757,13 @@ static void plat_mpc8xxx_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + fsl_spi_cpm_free(mpc8xxx_spi); + + spi_controller_put(host); } MODULE_ALIAS("platform:mpc8xxx_spi"); diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c index 216a0a91fc47..046bd894040b 100644 --- a/drivers/spi/spi-hisi-kunpeng.c +++ b/drivers/spi/spi-hisi-kunpeng.c @@ -196,9 +196,22 @@ static void hisi_spi_flush_fifo(struct hisi_spi *hs) unsigned long limit = loops_per_jiffy << 1; do { - while (hisi_spi_rx_not_empty(hs)) + unsigned long inner_limit = loops_per_jiffy; + + while (hisi_spi_rx_not_empty(hs) && --inner_limit) { readl(hs->regs + HISI_SPI_DOUT); - } while (hisi_spi_busy(hs) && limit--); + cpu_relax(); + } + + if (!inner_limit) { + dev_warn_ratelimited(hs->dev, "RX FIFO flush timeout\n"); + break; + } + + } while (hisi_spi_busy(hs) && --limit); + + if (!limit) + dev_warn_ratelimited(hs->dev, "SPI busy timeout\n"); } /* Disable the controller and all interrupts */ diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index 902fb64815c9..57625a3ce2f2 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -643,7 +643,7 @@ static int img_spfi_probe(struct platform_device *pdev) pm_runtime_set_active(spfi->dev); pm_runtime_enable(spfi->dev); - ret = devm_spi_register_controller(spfi->dev, host); + ret = spi_register_controller(host); if (ret) goto disable_pm; @@ -669,6 +669,10 @@ static void img_spfi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct img_spfi *spfi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + if (spfi->tx_ch) dma_release_channel(spfi->tx_ch); if (spfi->rx_ch) @@ -679,6 +683,8 @@ static void img_spfi_remove(struct platform_device *pdev) clk_disable_unprepare(spfi->spfi_clk); clk_disable_unprepare(spfi->sys_clk); } + + spi_controller_put(host); } #ifdef CONFIG_PM diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 64c6c09e1e7b..4747899e0646 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -2231,11 +2231,9 @@ static int spi_imx_probe(struct platform_device *pdev) target_mode = devtype_data->has_targetmode && of_property_read_bool(np, "spi-slave"); if (target_mode) - controller = spi_alloc_target(&pdev->dev, - sizeof(struct spi_imx_data)); + controller = devm_spi_alloc_target(&pdev->dev, sizeof(*spi_imx)); else - controller = spi_alloc_host(&pdev->dev, - sizeof(struct spi_imx_data)); + controller = devm_spi_alloc_host(&pdev->dev, sizeof(*spi_imx)); if (!controller) return -ENOMEM; @@ -2304,40 +2302,31 @@ static int spi_imx_probe(struct platform_device *pdev) init_completion(&spi_imx->xfer_done); spi_imx->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); - if (IS_ERR(spi_imx->base)) { - ret = PTR_ERR(spi_imx->base); - goto out_controller_put; - } + if (IS_ERR(spi_imx->base)) + return PTR_ERR(spi_imx->base); + spi_imx->base_phys = res->start; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - ret = irq; - goto out_controller_put; - } + if (irq < 0) + return irq; ret = devm_request_irq(&pdev->dev, irq, spi_imx_isr, 0, dev_name(&pdev->dev), spi_imx); - if (ret) { - dev_err(&pdev->dev, "can't get irq%d: %d\n", irq, ret); - goto out_controller_put; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "can't get irq%d\n", irq); spi_imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); - if (IS_ERR(spi_imx->clk_ipg)) { - ret = PTR_ERR(spi_imx->clk_ipg); - goto out_controller_put; - } + if (IS_ERR(spi_imx->clk_ipg)) + return PTR_ERR(spi_imx->clk_ipg); spi_imx->clk_per = devm_clk_get(&pdev->dev, "per"); - if (IS_ERR(spi_imx->clk_per)) { - ret = PTR_ERR(spi_imx->clk_per); - goto out_controller_put; - } + if (IS_ERR(spi_imx->clk_per)) + return PTR_ERR(spi_imx->clk_per); ret = clk_prepare_enable(spi_imx->clk_per); if (ret) - goto out_controller_put; + return ret; ret = clk_prepare_enable(spi_imx->clk_ipg); if (ret) @@ -2389,8 +2378,6 @@ out_runtime_pm_put: clk_disable_unprepare(spi_imx->clk_ipg); out_put_per: clk_disable_unprepare(spi_imx->clk_per); -out_controller_put: - spi_controller_put(controller); return ret; } diff --git a/drivers/spi/spi-lantiq-ssc.c b/drivers/spi/spi-lantiq-ssc.c index f83cb63c9d0c..75b9af8cb5db 100644 --- a/drivers/spi/spi-lantiq-ssc.c +++ b/drivers/spi/spi-lantiq-ssc.c @@ -994,7 +994,7 @@ static int lantiq_ssc_probe(struct platform_device *pdev) "Lantiq SSC SPI controller (Rev %i, TXFS %u, RXFS %u, DMA %u)\n", revision, spi->tx_fifo_size, spi->rx_fifo_size, supports_dma); - err = devm_spi_register_controller(dev, host); + err = spi_register_controller(host); if (err) { dev_err(dev, "failed to register spi host\n"); goto err_wq_destroy; @@ -1016,6 +1016,10 @@ static void lantiq_ssc_remove(struct platform_device *pdev) { struct lantiq_ssc_spi *spi = platform_get_drvdata(pdev); + spi_controller_get(spi->host); + + spi_unregister_controller(spi->host); + lantiq_ssc_writel(spi, 0, LTQ_SPI_IRNEN); lantiq_ssc_writel(spi, 0, LTQ_SPI_CLC); rx_fifo_flush(spi); @@ -1024,6 +1028,8 @@ static void lantiq_ssc_remove(struct platform_device *pdev) destroy_workqueue(spi->wq); clk_put(spi->fpi_clk); + + spi_controller_put(spi->host); } static struct platform_driver lantiq_ssc_driver = { diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c index 57768da3205d..b80f9f457b66 100644 --- a/drivers/spi/spi-meson-spicc.c +++ b/drivers/spi/spi-meson-spicc.c @@ -1081,7 +1081,7 @@ static int meson_spicc_probe(struct platform_device *pdev) } } - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&pdev->dev, "spi registration failed\n"); goto out_host; @@ -1099,8 +1099,14 @@ static void meson_spicc_remove(struct platform_device *pdev) { struct meson_spicc_device *spicc = platform_get_drvdata(pdev); + spi_controller_get(spicc->host); + + spi_unregister_controller(spicc->host); + /* Disable SPI */ writel(0, spicc->base + SPICC_CONREG); + + spi_controller_put(spicc->host); } static const struct meson_spicc_data meson_spicc_gx_data = { diff --git a/drivers/spi/spi-microchip-core-qspi.c b/drivers/spi/spi-microchip-core-qspi.c index aafe6cbf2aea..eab059fb0bc2 100644 --- a/drivers/spi/spi-microchip-core-qspi.c +++ b/drivers/spi/spi-microchip-core-qspi.c @@ -692,7 +692,7 @@ static int mchp_coreqspi_probe(struct platform_device *pdev) return -ENOMEM; qspi = spi_controller_get_devdata(ctlr); - platform_set_drvdata(pdev, qspi); + platform_set_drvdata(pdev, ctlr); qspi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(qspi->regs)) @@ -732,7 +732,7 @@ static int mchp_coreqspi_probe(struct platform_device *pdev) ctlr->num_chipselect = 2; ctlr->use_gpio_descriptors = true; - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret) return dev_err_probe(&pdev->dev, ret, "spi_register_controller failed\n"); @@ -742,9 +742,13 @@ static int mchp_coreqspi_probe(struct platform_device *pdev) static void mchp_coreqspi_remove(struct platform_device *pdev) { - struct mchp_coreqspi *qspi = platform_get_drvdata(pdev); - u32 control = readl_relaxed(qspi->regs + REG_CONTROL); + struct spi_controller *ctlr = platform_get_drvdata(pdev); + struct mchp_coreqspi *qspi = spi_controller_get_devdata(ctlr); + u32 control; + spi_unregister_controller(ctlr); + + control = readl_relaxed(qspi->regs + REG_CONTROL); mchp_coreqspi_disable_ints(qspi); control &= ~CONTROL_ENABLE; writel_relaxed(control, qspi->regs + REG_CONTROL); diff --git a/drivers/spi/spi-microchip-core-spi.c b/drivers/spi/spi-microchip-core-spi.c index a4c128ae391b..be01c178e2b0 100644 --- a/drivers/spi/spi-microchip-core-spi.c +++ b/drivers/spi/spi-microchip-core-spi.c @@ -384,7 +384,7 @@ static int mchp_corespi_probe(struct platform_device *pdev) mchp_corespi_init(host, spi); - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) { mchp_corespi_disable_ints(spi); mchp_corespi_disable(spi); @@ -399,6 +399,8 @@ static void mchp_corespi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct mchp_corespi *spi = spi_controller_get_devdata(host); + spi_unregister_controller(host); + mchp_corespi_disable_ints(spi); mchp_corespi_disable(spi); } diff --git a/drivers/spi/spi-mpfs.c b/drivers/spi/spi-mpfs.c index 64d15a6188ac..989a379b0700 100644 --- a/drivers/spi/spi-mpfs.c +++ b/drivers/spi/spi-mpfs.c @@ -574,7 +574,7 @@ static int mpfs_spi_probe(struct platform_device *pdev) mpfs_spi_init(host, spi); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { mpfs_spi_disable_ints(spi); mpfs_spi_disable(spi); @@ -592,6 +592,8 @@ static void mpfs_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct mpfs_spi *spi = spi_controller_get_devdata(host); + spi_unregister_controller(host); + mpfs_spi_disable_ints(spi); mpfs_spi_disable(spi); } diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 0368a26bca9a..96f8555be983 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -1325,7 +1325,7 @@ static int mtk_spi_probe(struct platform_device *pdev) pm_runtime_enable(dev); - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) { pm_runtime_disable(dev); return dev_err_probe(dev, ret, "failed to register host\n"); @@ -1340,6 +1340,8 @@ static void mtk_spi_remove(struct platform_device *pdev) struct mtk_spi *mdata = spi_controller_get_devdata(host); int ret; + spi_unregister_controller(host); + cpu_latency_qos_remove_request(&mdata->qos_request); if (mdata->use_spimem && !completion_done(&mdata->spimem_done)) complete(&mdata->spimem_done); diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c index 1e5ec0840174..74f34537b02c 100644 --- a/drivers/spi/spi-mtk-nor.c +++ b/drivers/spi/spi-mtk-nor.c @@ -913,7 +913,7 @@ static int mtk_nor_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_get_noresume(&pdev->dev); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) goto err_probe; @@ -938,6 +938,8 @@ static void mtk_nor_remove(struct platform_device *pdev) struct spi_controller *ctlr = dev_get_drvdata(&pdev->dev); struct mtk_nor *sp = spi_controller_get_devdata(ctlr); + spi_unregister_controller(ctlr); + pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); diff --git a/drivers/spi/spi-mtk-snfi.c b/drivers/spi/spi-mtk-snfi.c index 437edbd658aa..73fa84475f0e 100644 --- a/drivers/spi/spi-mtk-snfi.c +++ b/drivers/spi/spi-mtk-snfi.c @@ -1303,6 +1303,13 @@ static const struct spi_controller_mem_caps mtk_snand_mem_caps = { .ecc = true, }; +static void mtk_unregister_ecc_engine(void *data) +{ + struct nand_ecc_engine *eng = data; + + nand_ecc_unregister_on_host_hw_engine(eng); +} + static irqreturn_t mtk_snand_irq(int irq, void *id) { struct mtk_snand *snf = id; @@ -1443,6 +1450,13 @@ static int mtk_snand_probe(struct platform_device *pdev) goto release_ecc; } + ret = devm_add_action_or_reset(&pdev->dev, mtk_unregister_ecc_engine, + &ms->ecc_eng); + if (ret) { + dev_err_probe(&pdev->dev, ret, "failed to add ECC unregister action\n"); + goto release_ecc; + } + ctlr->num_chipselect = 1; ctlr->mem_ops = &mtk_snand_mem_ops; ctlr->mem_caps = &mtk_snand_mem_caps; diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index b3301c69e2de..0164e04d59a1 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -619,7 +619,7 @@ static int mxs_spi_probe(struct platform_device *pdev) if (ret) goto out_pm_runtime_put; - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&pdev->dev, "Cannot register SPI host, %d\n", ret); goto out_pm_runtime_put; @@ -650,11 +650,17 @@ static void mxs_spi_remove(struct platform_device *pdev) spi = spi_controller_get_devdata(host); ssp = &spi->ssp; + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) mxs_spi_runtime_suspend(&pdev->dev); dma_release_channel(ssp->dmach); + + spi_controller_put(host); } static struct platform_driver mxs_spi_driver = { diff --git a/drivers/spi/spi-npcm-fiu.c b/drivers/spi/spi-npcm-fiu.c index 3961b0ccdb4b..6617751009c3 100644 --- a/drivers/spi/spi-npcm-fiu.c +++ b/drivers/spi/spi-npcm-fiu.c @@ -715,7 +715,6 @@ static int npcm_fiu_probe(struct platform_device *pdev) fiu->info = &fiu_data_match->npcm_fiu_data_info[id]; - platform_set_drvdata(pdev, fiu); fiu->dev = dev; regbase = devm_platform_ioremap_resource_byname(pdev, "control"); @@ -738,8 +737,6 @@ static int npcm_fiu_probe(struct platform_device *pdev) fiu->spix_mode = of_property_read_bool(dev->of_node, "nuvoton,spix-mode"); - platform_set_drvdata(pdev, fiu); - ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_DUAL | SPI_TX_QUAD; ctrl->setup = npcm_fiu_setup; @@ -750,10 +747,6 @@ static int npcm_fiu_probe(struct platform_device *pdev) return devm_spi_register_controller(dev, ctrl); } -static void npcm_fiu_remove(struct platform_device *pdev) -{ -} - MODULE_DEVICE_TABLE(of, npcm_fiu_dt_ids); static struct platform_driver npcm_fiu_driver = { @@ -763,7 +756,6 @@ static struct platform_driver npcm_fiu_driver = { .of_match_table = npcm_fiu_dt_ids, }, .probe = npcm_fiu_probe, - .remove = npcm_fiu_remove, }; module_platform_driver(npcm_fiu_driver); diff --git a/drivers/spi/spi-npcm-pspi.c b/drivers/spi/spi-npcm-pspi.c index e60b3cc398ec..cffef0a5977d 100644 --- a/drivers/spi/spi-npcm-pspi.c +++ b/drivers/spi/spi-npcm-pspi.c @@ -413,7 +413,7 @@ static int npcm_pspi_probe(struct platform_device *pdev) /* set to default clock rate */ npcm_pspi_set_baudrate(priv, NPCM_PSPI_DEFAULT_CLK); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) goto out_disable_clk; @@ -434,8 +434,14 @@ static void npcm_pspi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct npcm_pspi *priv = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + npcm_pspi_reset_hw(priv); clk_disable_unprepare(priv->clk); + + spi_controller_put(host); } static const struct of_device_id npcm_pspi_match[] = { diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index 320b3d93df57..1e36ae084dd8 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -996,7 +996,7 @@ static int nxp_fspi_do_op(struct nxp_fspi *f, const struct spi_mem_op *op) reg = reg | FSPI_IPRXFCR_CLR; fspi_writel(f, reg, base + FSPI_IPRXFCR); - init_completion(&f->c); + reinit_completion(&f->c); fspi_writel(f, op->addr.val, base + FSPI_IPCR0); /* @@ -1365,6 +1365,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) if (ret < 0) return dev_err_probe(dev, ret, "Failed to disable clock"); + init_completion(&f->c); ret = devm_request_irq(dev, irq, nxp_fspi_irq_handler, 0, pdev->name, f); if (ret) diff --git a/drivers/spi/spi-nxp-xspi.c b/drivers/spi/spi-nxp-xspi.c index 06fcdf22990b..385302a6e62f 100644 --- a/drivers/spi/spi-nxp-xspi.c +++ b/drivers/spi/spi-nxp-xspi.c @@ -958,7 +958,7 @@ static int nxp_xspi_do_op(struct nxp_xspi *xspi, const struct spi_mem_op *op) writel(reg, base + XSPI_RBCT); } - init_completion(&xspi->c); + reinit_completion(&xspi->c); /* Config the data address */ writel(op->addr.val + xspi->memmap_phy, base + XSPI_SFP_TG_SFAR); @@ -1273,6 +1273,7 @@ static int nxp_xspi_probe(struct platform_device *pdev) nxp_xspi_default_setup(xspi); + init_completion(&xspi->c); ret = devm_request_irq(dev, irq, nxp_xspi_irq_handler, 0, pdev->name, xspi); if (ret) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 2207e05c9d06..56b30ff58771 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -942,10 +942,16 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, l = mcspi_cached_chconf0(spi); - /* standard 4-wire host mode: SCK, MOSI/out, MISO/in, nCS - * REVISIT: this controller could support SPI_3WIRE mode. - */ - if (mcspi->pin_dir == MCSPI_PINDIR_D0_IN_D1_OUT) { + if (spi->mode & SPI_3WIRE) { + if (t && !t->tx_buf) { + l &= ~OMAP2_MCSPI_CHCONF_IS; + l |= OMAP2_MCSPI_CHCONF_DPE0; + } else if (t && !t->rx_buf) { + l |= OMAP2_MCSPI_CHCONF_IS; + l &= ~OMAP2_MCSPI_CHCONF_DPE0; + } + l |= OMAP2_MCSPI_CHCONF_DPE1; + } else if (mcspi->pin_dir == MCSPI_PINDIR_D0_IN_D1_OUT) { l &= ~OMAP2_MCSPI_CHCONF_IS; l &= ~OMAP2_MCSPI_CHCONF_DPE1; l |= OMAP2_MCSPI_CHCONF_DPE0; @@ -1178,6 +1184,7 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr, omap2_mcspi_set_cs(spi, spi->mode & SPI_CS_HIGH); if (par_override || + (spi->mode & SPI_3WIRE) || (t->speed_hz != spi->max_speed_hz) || (t->bits_per_word != spi->bits_per_word)) { par_override = 1; @@ -1484,7 +1491,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) return -ENOMEM; /* the spi->mode bits understood by this driver: */ - ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_3WIRE; ctlr->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); ctlr->setup = omap2_mcspi_setup; ctlr->auto_runtime_pm = true; @@ -1585,7 +1592,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) if (status < 0) goto disable_pm; - status = devm_spi_register_controller(&pdev->dev, ctlr); + status = spi_register_controller(ctlr); if (status < 0) goto disable_pm; @@ -1606,11 +1613,17 @@ static void omap2_mcspi_remove(struct platform_device *pdev) struct spi_controller *ctlr = platform_get_drvdata(pdev); struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr); + spi_controller_get(ctlr); + + spi_unregister_controller(ctlr); + omap2_mcspi_release_dma(ctlr); pm_runtime_dont_use_autosuspend(mcspi->dev); pm_runtime_put_sync(mcspi->dev); pm_runtime_disable(&pdev->dev); + + spi_controller_put(ctlr); } /* work with hotplug and coldplug */ diff --git a/drivers/spi/spi-pic32-sqi.c b/drivers/spi/spi-pic32-sqi.c index 051590038895..41662992dbe5 100644 --- a/drivers/spi/spi-pic32-sqi.c +++ b/drivers/spi/spi-pic32-sqi.c @@ -642,7 +642,7 @@ static int pic32_sqi_probe(struct platform_device *pdev) host->prepare_transfer_hardware = pic32_sqi_prepare_hardware; host->unprepare_transfer_hardware = pic32_sqi_unprepare_hardware; - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&host->dev, "failed registering spi host\n"); free_irq(sqi->irq, sqi); @@ -665,9 +665,15 @@ static void pic32_sqi_remove(struct platform_device *pdev) { struct pic32_sqi *sqi = platform_get_drvdata(pdev); + spi_controller_get(sqi->host); + + spi_unregister_controller(sqi->host); + /* release resources */ free_irq(sqi->irq, sqi); ring_desc_ring_free(sqi); + + spi_controller_put(sqi->host); } static const struct of_device_id pic32_sqi_of_ids[] = { diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c index 369850d14313..70427e529945 100644 --- a/drivers/spi/spi-pic32.c +++ b/drivers/spi/spi-pic32.c @@ -821,7 +821,7 @@ static int pic32_spi_probe(struct platform_device *pdev) } /* register host */ - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&host->dev, "failed registering spi host\n"); goto err_bailout; @@ -840,11 +840,16 @@ err_host: static void pic32_spi_remove(struct platform_device *pdev) { - struct pic32_spi *pic32s; + struct pic32_spi *pic32s = platform_get_drvdata(pdev); + + spi_controller_get(pic32s->host); + + spi_unregister_controller(pic32s->host); - pic32s = platform_get_drvdata(pdev); pic32_spi_disable(pic32s); pic32_spi_dma_unprep(pic32s); + + spi_controller_put(pic32s->host); } static const struct of_device_id pic32_spi_of_match[] = { diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index c82cc522776d..9c0211f94fd0 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -1127,11 +1127,11 @@ static inline void pl022_dma_remove(struct pl022 *pl022) * * This function handles interrupts generated for an interrupt based transfer. * If a receive overrun (ROR) interrupt is there then we disable SSP, flag the - * current message's state as STATE_ERROR and schedule the tasklet - * pump_transfers which will do the postprocessing of the current message by - * calling giveback(). Otherwise it reads data from RX FIFO till there is no - * more data, and writes data in TX FIFO till it is not full. If we complete - * the transfer we move to the next transfer and schedule the tasklet. + * current transfer with SPI_TRANS_FAIL_IO and call + * spi_finalize_current_transfer() to let the core finish the message. + * Otherwise it reads data from RX FIFO till there is no more data, and writes + * data in TX FIFO till it is not full. When the transfer is complete we call + * spi_finalize_current_transfer() so the core can schedule the next one. */ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id) { @@ -1956,7 +1956,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) /* Register with the SPI framework */ amba_set_drvdata(adev, pl022); - status = devm_spi_register_controller(&adev->dev, host); + status = spi_register_controller(host); if (status != 0) { dev_err_probe(&adev->dev, status, "problem registering spi host\n"); @@ -1997,6 +1997,10 @@ pl022_remove(struct amba_device *adev) if (!pl022) return; + spi_controller_get(pl022->host); + + spi_unregister_controller(pl022->host); + /* * undo pm_runtime_put() in probe. I assume that we're not * accessing the primecell here. @@ -2008,6 +2012,8 @@ pl022_remove(struct amba_device *adev) pl022_dma_remove(pl022); amba_release_regions(adev); + + spi_controller_put(pl022->host); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c index 08cb6e96ac94..c94d1d192e74 100644 --- a/drivers/spi/spi-pxa2xx-dma.c +++ b/drivers/spi/spi-pxa2xx-dma.c @@ -29,9 +29,9 @@ static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data, /* * It is possible that one CPU is handling ROR interrupt and other - * just gets DMA completion. Calling pump_transfers() twice for the - * same transfer leads to problems thus we prevent concurrent calls - * by using dma_running. + * just gets DMA completion. Calling spi_finalize_current_transfer() + * twice for the same transfer leads to problems thus we prevent + * concurrent calls by using dma_running. */ if (atomic_dec_and_test(&drv_data->dma_running)) { /* diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index f7881a31e4cc..6291d7c2e06f 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -796,7 +796,7 @@ static irqreturn_t ssp_int(int irq, void *dev_id) * The function calculates parameters for all cases and chooses the one closest * to the asked baud rate. */ -static unsigned int quark_x1000_get_clk_div(int rate, u32 *dds) +static unsigned int quark_x1000_get_clk_div(u32 rate, u32 *dds) { unsigned long xtal = 200000000; unsigned long fref = xtal / 2; /* mandatory division by 2, @@ -885,12 +885,12 @@ static unsigned int quark_x1000_get_clk_div(int rate, u32 *dds) return q - 1; } -static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate) +static unsigned int ssp_get_clk_div(struct driver_data *drv_data, u32 rate) { - unsigned long ssp_clk = drv_data->controller->max_speed_hz; + u32 ssp_clk = drv_data->controller->max_speed_hz; const struct ssp_device *ssp = drv_data->ssp; - rate = min_t(int, ssp_clk, rate); + rate = min(ssp_clk, rate); /* * Calculate the divisor for the SCR (Serial Clock Rate), avoiding @@ -902,8 +902,7 @@ static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate) return (DIV_ROUND_UP(ssp_clk, rate) - 1) & 0xfff; } -static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data, - int rate) +static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data, u32 rate) { struct chip_data *chip = spi_get_ctldata(drv_data->controller->cur_msg->spi); diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index 6cbdcd060e8c..45d9b4cb75e4 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -1193,7 +1193,7 @@ static int spi_qup_probe(struct platform_device *pdev) pm_runtime_set_active(dev); pm_runtime_enable(dev); - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) goto disable_pm; @@ -1320,6 +1320,10 @@ static void spi_qup_remove(struct platform_device *pdev) struct spi_qup *controller = spi_controller_get_devdata(host); int ret; + spi_controller_get(host); + + spi_unregister_controller(host); + ret = pm_runtime_get_sync(&pdev->dev); if (ret >= 0) { @@ -1339,6 +1343,8 @@ static void spi_qup_remove(struct platform_device *pdev) pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + + spi_controller_put(host); } static const struct of_device_id spi_qup_dt_match[] = { diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index fd2ebef4903f..14cd1b9d9793 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -767,9 +767,9 @@ static int rockchip_spi_probe(struct platform_device *pdev) target_mode = of_property_read_bool(np, "spi-slave"); if (target_mode) - ctlr = spi_alloc_target(&pdev->dev, sizeof(struct rockchip_spi)); + ctlr = devm_spi_alloc_target(&pdev->dev, sizeof(*rs)); else - ctlr = spi_alloc_host(&pdev->dev, sizeof(struct rockchip_spi)); + ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*rs)); if (!ctlr) return -ENOMEM; @@ -780,35 +780,31 @@ static int rockchip_spi_probe(struct platform_device *pdev) /* Get basic io resource and map it */ rs->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &mem); - if (IS_ERR(rs->regs)) { - ret = PTR_ERR(rs->regs); - goto err_put_ctlr; - } + if (IS_ERR(rs->regs)) + return PTR_ERR(rs->regs); rs->apb_pclk = devm_clk_get_enabled(&pdev->dev, "apb_pclk"); if (IS_ERR(rs->apb_pclk)) { - ret = dev_err_probe(&pdev->dev, PTR_ERR(rs->apb_pclk), - "Failed to get apb_pclk\n"); - goto err_put_ctlr; + return dev_err_probe(&pdev->dev, PTR_ERR(rs->apb_pclk), + "Failed to get apb_pclk\n"); } rs->spiclk = devm_clk_get_enabled(&pdev->dev, "spiclk"); if (IS_ERR(rs->spiclk)) { - ret = dev_err_probe(&pdev->dev, PTR_ERR(rs->spiclk), - "Failed to get spi_pclk\n"); - goto err_put_ctlr; + return dev_err_probe(&pdev->dev, PTR_ERR(rs->spiclk), + "Failed to get spi_pclk\n"); } spi_enable_chip(rs, false); ret = platform_get_irq(pdev, 0); if (ret < 0) - goto err_put_ctlr; + return ret; ret = devm_request_irq(&pdev->dev, ret, rockchip_spi_isr, 0, dev_name(&pdev->dev), ctlr); if (ret) - goto err_put_ctlr; + return ret; rs->dev = &pdev->dev; rs->freq = clk_get_rate(rs->spiclk); @@ -830,10 +826,8 @@ static int rockchip_spi_probe(struct platform_device *pdev) } rs->fifo_len = get_fifo_len(rs); - if (!rs->fifo_len) { - ret = dev_err_probe(&pdev->dev, -EINVAL, "Failed to get fifo length\n"); - goto err_put_ctlr; - } + if (!rs->fifo_len) + return dev_err_probe(&pdev->dev, -EINVAL, "Failed to get fifo length\n"); pm_runtime_set_autosuspend_delay(&pdev->dev, ROCKCHIP_AUTOSUSPEND_TIMEOUT); pm_runtime_use_autosuspend(&pdev->dev); @@ -908,7 +902,7 @@ static int rockchip_spi_probe(struct platform_device *pdev) break; } - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { dev_err(&pdev->dev, "Failed to register controller\n"); goto err_free_dma_rx; @@ -924,18 +918,18 @@ err_free_dma_tx: dma_release_channel(ctlr->dma_tx); err_disable_pm_runtime: pm_runtime_disable(&pdev->dev); -err_put_ctlr: - spi_controller_put(ctlr); return ret; } static void rockchip_spi_remove(struct platform_device *pdev) { - struct spi_controller *ctlr = spi_controller_get(platform_get_drvdata(pdev)); + struct spi_controller *ctlr = platform_get_drvdata(pdev); pm_runtime_get_sync(&pdev->dev); + spi_unregister_controller(ctlr); + pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); @@ -944,8 +938,6 @@ static void rockchip_spi_remove(struct platform_device *pdev) dma_release_channel(ctlr->dma_tx); if (ctlr->dma_rx) dma_release_channel(ctlr->dma_rx); - - spi_controller_put(ctlr); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index c739c1998b4c..a8180dece716 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -1171,8 +1171,14 @@ static void rspi_remove(struct platform_device *pdev) { struct rspi_data *rspi = platform_get_drvdata(pdev); + spi_controller_get(rspi->ctlr); + + spi_unregister_controller(rspi->ctlr); + rspi_release_dma(rspi->ctlr); pm_runtime_disable(&pdev->dev); + + spi_controller_put(rspi->ctlr); } static const struct spi_ops rspi_ops = { @@ -1376,9 +1382,9 @@ static int rspi_probe(struct platform_device *pdev) if (ret < 0) dev_warn(&pdev->dev, "DMA not available, using PIO\n"); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); + dev_err(&pdev->dev, "failed to register controller\n"); goto error3; } diff --git a/drivers/spi/spi-rzv2h-rspi.c b/drivers/spi/spi-rzv2h-rspi.c index 23f0e92ae208..f45af5884638 100644 --- a/drivers/spi/spi-rzv2h-rspi.c +++ b/drivers/spi/spi-rzv2h-rspi.c @@ -50,7 +50,6 @@ /* Register SPBR */ #define RSPI_SPBR_SPR_MIN 0 -#define RSPI_SPBR_SPR_PCLK_MIN 1 #define RSPI_SPBR_SPR_MAX 255 /* Register SPCMD */ @@ -77,6 +76,8 @@ #define RSPI_RESET_NUM 2 +#define RSPI_MAX_SPEED_HZ 50000000 + struct rzv2h_rspi_best_clock { struct clk *clk; unsigned long clk_rate; @@ -87,9 +88,9 @@ struct rzv2h_rspi_best_clock { }; struct rzv2h_rspi_info { - void (*find_tclk_rate)(struct clk *clk, u32 hz, u8 spr_min, u8 spr_max, + void (*find_tclk_rate)(struct clk *clk, u32 hz, struct rzv2h_rspi_best_clock *best_clk); - void (*find_pclk_rate)(struct clk *clk, u32 hz, u8 spr_low, u8 spr_high, + void (*find_pclk_rate)(struct clk *clk, u32 hz, struct rzv2h_rspi_best_clock *best_clk); const char *tclk_name; unsigned int fifo_size; @@ -412,7 +413,6 @@ static inline u32 rzv2h_rspi_calc_bitrate(unsigned long tclk_rate, u8 spr, } static void rzv2h_rspi_find_rate_variable(struct clk *clk, u32 hz, - u8 spr_min, u8 spr_max, struct rzv2h_rspi_best_clock *best) { long clk_rate, clk_min_rate, clk_max_rate; @@ -463,7 +463,7 @@ static void rzv2h_rspi_find_rate_variable(struct clk *clk, u32 hz, * minimum SPR that is in the valid range. */ min_rate_spr = DIV_ROUND_CLOSEST(clk_min_rate, rate_div) - 1; - if (min_rate_spr > spr_max) + if (min_rate_spr > RSPI_SPBR_SPR_MAX) continue; /* @@ -473,14 +473,14 @@ static void rzv2h_rspi_find_rate_variable(struct clk *clk, u32 hz, * maximum SPR that is in the valid range. */ max_rate_spr = DIV_ROUND_CLOSEST(clk_max_rate, rate_div) - 1; - if (max_rate_spr < spr_min) + if (max_rate_spr < RSPI_SPBR_SPR_MIN) break; - if (min_rate_spr < spr_min) - min_rate_spr = spr_min; + if (min_rate_spr < RSPI_SPBR_SPR_MIN) + min_rate_spr = RSPI_SPBR_SPR_MIN; - if (max_rate_spr > spr_max) - max_rate_spr = spr_max; + if (max_rate_spr > RSPI_SPBR_SPR_MAX) + max_rate_spr = RSPI_SPBR_SPR_MAX; for (spr = min_rate_spr; spr <= max_rate_spr; spr++) { clk_rate = (spr + 1) * rate_div; @@ -511,7 +511,6 @@ static void rzv2h_rspi_find_rate_variable(struct clk *clk, u32 hz, } static void rzv2h_rspi_find_rate_fixed(struct clk *clk, u32 hz, - u8 spr_min, u8 spr_max, struct rzv2h_rspi_best_clock *best) { unsigned long clk_rate; @@ -533,7 +532,18 @@ static void rzv2h_rspi_find_rate_fixed(struct clk *clk, u32 hz, for (brdv = RSPI_SPCMD_BRDV_MIN; brdv <= RSPI_SPCMD_BRDV_MAX; brdv++) { spr = DIV_ROUND_UP(clk_rate, hz * (1 << (brdv + 1))); spr--; - if (spr >= spr_min && spr <= spr_max) + /* + * Skip SPR=0 and BRDV=0 as it is not a valid combination: + * - On RZ/G3E, RZ/G3L, RZ/V2H(P) and RZ/V2N, RSPI_n_TCLK is + * fixed at 200MHz and SPR=0 and BRDV=0 results in the maximum + * bit rate of 100Mbps which is prohibited. + * - On RZ/T2H and RZ/N2H, when PCLK (125MHz) is used as + * the clock source, SPR=0 and BRDV=0 is explicitly listed + * as unsupported in the hardware manual (Table 36.7). + */ + if (!spr && !brdv) + continue; + if (spr >= RSPI_SPBR_SPR_MIN && spr <= RSPI_SPBR_SPR_MAX) goto clock_found; } @@ -563,16 +573,10 @@ static u32 rzv2h_rspi_setup_clock(struct rzv2h_rspi_priv *rspi, u32 hz) }; int ret; - rspi->info->find_tclk_rate(rspi->tclk, hz, RSPI_SPBR_SPR_MIN, - RSPI_SPBR_SPR_MAX, &best_clock); + rspi->info->find_tclk_rate(rspi->tclk, hz, &best_clock); - /* - * T2H and N2H can also use PCLK as a source, which is 125MHz, but not - * when both SPR and BRDV are 0. - */ if (best_clock.error && rspi->info->find_pclk_rate) - rspi->info->find_pclk_rate(rspi->pclk, hz, RSPI_SPBR_SPR_PCLK_MIN, - RSPI_SPBR_SPR_MAX, &best_clock); + rspi->info->find_pclk_rate(rspi->pclk, hz, &best_clock); if (!best_clock.clk_rate) return -EINVAL; @@ -771,13 +775,7 @@ static int rzv2h_rspi_probe(struct platform_device *pdev) RSPI_SPBR_SPR_MAX, RSPI_SPCMD_BRDV_MAX); - tclk_rate = clk_round_rate(rspi->tclk, ULONG_MAX); - if (tclk_rate < 0) - return tclk_rate; - - controller->max_speed_hz = rzv2h_rspi_calc_bitrate(tclk_rate, - RSPI_SPBR_SPR_MIN, - RSPI_SPCMD_BRDV_MIN); + controller->max_speed_hz = RSPI_MAX_SPEED_HZ; controller->dma_tx = devm_dma_request_chan(dev, "tx"); if (IS_ERR(controller->dma_tx)) { @@ -811,6 +809,13 @@ static const struct rzv2h_rspi_info rzv2h_info = { .num_clks = 3, }; +static const struct rzv2h_rspi_info rzg3l_info = { + .find_tclk_rate = rzv2h_rspi_find_rate_fixed, + .tclk_name = "tclk", + .fifo_size = 16, + .num_clks = 2, +}; + static const struct rzv2h_rspi_info rzt2h_info = { .find_tclk_rate = rzv2h_rspi_find_rate_variable, .find_pclk_rate = rzv2h_rspi_find_rate_fixed, @@ -820,6 +825,7 @@ static const struct rzv2h_rspi_info rzt2h_info = { }; static const struct of_device_id rzv2h_rspi_match[] = { + { .compatible = "renesas,r9a08g046-rspi", &rzg3l_info }, { .compatible = "renesas,r9a09g057-rspi", &rzv2h_info }, { .compatible = "renesas,r9a09g077-rspi", &rzt2h_info }, { /* sentinel */ } diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index ba85243d6d89..37176e557099 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1369,7 +1369,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN, sdd->regs + S3C64XX_SPI_INT_EN); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret != 0) { dev_err(&pdev->dev, "cannot register SPI host: %d\n", ret); goto err_pm_put; @@ -1399,12 +1399,9 @@ static void s3c64xx_spi_remove(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); - writel(0, sdd->regs + S3C64XX_SPI_INT_EN); + spi_unregister_controller(host); - if (!is_polling(sdd)) { - dma_release_channel(sdd->rx_dma.ch); - dma_release_channel(sdd->tx_dma.ch); - } + writel(0, sdd->regs + S3C64XX_SPI_INT_EN); pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c index e03eaca1b1a7..1e3ca718ca73 100644 --- a/drivers/spi/spi-sh-hspi.c +++ b/drivers/spi/spi-sh-hspi.c @@ -257,9 +257,9 @@ static int hspi_probe(struct platform_device *pdev) ctlr->transfer_one_message = hspi_transfer_one_message; ctlr->bits_per_word_mask = SPI_BPW_MASK(8); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); + dev_err(&pdev->dev, "failed to register controller\n"); goto error2; } @@ -279,9 +279,15 @@ static void hspi_remove(struct platform_device *pdev) { struct hspi_priv *hspi = platform_get_drvdata(pdev); + spi_controller_get(hspi->ctlr); + + spi_unregister_controller(hspi->ctlr); + pm_runtime_disable(&pdev->dev); clk_put(hspi->clk); + + spi_controller_put(hspi->ctlr); } static const struct of_device_id hspi_of_match[] = { diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 7f3e08810560..f114b6313f4f 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -1289,9 +1289,9 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) if (ret < 0) dev_warn(dev, "DMA not available, using PIO\n"); - ret = devm_spi_register_controller(dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(dev, "devm_spi_register_controller error.\n"); + dev_err(dev, "failed to register controller\n"); goto err2; } @@ -1309,8 +1309,14 @@ static void sh_msiof_spi_remove(struct platform_device *pdev) { struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev); + spi_controller_get(p->ctlr); + + spi_unregister_controller(p->ctlr); + sh_msiof_release_dma(p); pm_runtime_disable(&pdev->dev); + + spi_controller_put(p->ctlr); } static const struct platform_device_id spi_driver_ids[] = { diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c index 6c7aba8befa0..74a3e32fd2b5 100644 --- a/drivers/spi/spi-sifive.c +++ b/drivers/spi/spi-sifive.c @@ -312,7 +312,8 @@ static int sifive_spi_probe(struct platform_device *pdev) goto put_host; } - spi->clk = devm_clk_get(&pdev->dev, NULL); + /* Spin up the bus clock before hitting registers */ + spi->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(spi->clk)) { dev_err(&pdev->dev, "Unable to find bus clock\n"); ret = PTR_ERR(spi->clk); @@ -342,13 +343,6 @@ static int sifive_spi_probe(struct platform_device *pdev) goto put_host; } - /* Spin up the bus clock before hitting registers */ - ret = clk_prepare_enable(spi->clk); - if (ret) { - dev_err(&pdev->dev, "Unable to enable bus clock\n"); - goto put_host; - } - /* probe the number of CS lines */ spi->cs_inactive = sifive_spi_read(spi, SIFIVE_SPI_REG_CSDEF); sifive_spi_write(spi, SIFIVE_SPI_REG_CSDEF, 0xffffffffU); @@ -357,14 +351,14 @@ static int sifive_spi_probe(struct platform_device *pdev) if (!cs_bits) { dev_err(&pdev->dev, "Could not auto probe CS lines\n"); ret = -EINVAL; - goto disable_clk; + goto put_host; } num_cs = ilog2(cs_bits) + 1; if (num_cs > SIFIVE_SPI_MAX_CS) { dev_err(&pdev->dev, "Invalid number of spi targets\n"); ret = -EINVAL; - goto disable_clk; + goto put_host; } /* Define our host */ @@ -392,22 +386,20 @@ static int sifive_spi_probe(struct platform_device *pdev) dev_name(&pdev->dev), spi); if (ret) { dev_err(&pdev->dev, "Unable to bind to interrupt\n"); - goto disable_clk; + goto put_host; } dev_info(&pdev->dev, "mapped; irq=%d, cs=%d\n", irq, host->num_chipselect); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret < 0) { dev_err(&pdev->dev, "spi_register_host failed\n"); - goto disable_clk; + goto put_host; } return 0; -disable_clk: - clk_disable_unprepare(spi->clk); put_host: spi_controller_put(host); @@ -419,9 +411,14 @@ static void sifive_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct sifive_spi *spi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + /* Disable all the interrupts just in case */ sifive_spi_write(spi, SIFIVE_SPI_REG_IE, 0); - clk_disable_unprepare(spi->clk); + + spi_controller_put(host); } static int sifive_spi_suspend(struct device *dev) diff --git a/drivers/spi/spi-slave-mt27xx.c b/drivers/spi/spi-slave-mt27xx.c index ce889cb33228..7aedeaa5889d 100644 --- a/drivers/spi/spi-slave-mt27xx.c +++ b/drivers/spi/spi-slave-mt27xx.c @@ -453,7 +453,7 @@ static int mtk_spi_slave_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); clk_disable_unprepare(mdata->spi_clk); if (ret) { dev_err(&pdev->dev, @@ -473,7 +473,15 @@ err_put_ctlr: static void mtk_spi_slave_remove(struct platform_device *pdev) { + struct spi_controller *ctlr = platform_get_drvdata(pdev); + + spi_controller_get(ctlr); + + spi_unregister_controller(ctlr); + pm_runtime_disable(&pdev->dev); + + spi_controller_put(ctlr); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/spi-sn-f-ospi.c b/drivers/spi/spi-sn-f-ospi.c index 3c61c799723b..b459d51cb3a8 100644 --- a/drivers/spi/spi-sn-f-ospi.c +++ b/drivers/spi/spi-sn-f-ospi.c @@ -625,7 +625,7 @@ static int f_ospi_probe(struct platform_device *pdev) of_property_read_u32(dev->of_node, "num-cs", &num_cs); if (num_cs > OSPI_NUM_CS) { dev_err(dev, "num-cs too large: %d\n", num_cs); - return -ENOMEM; + return -EINVAL; } ctlr->num_chipselect = num_cs; diff --git a/drivers/spi/spi-sprd.c b/drivers/spi/spi-sprd.c index 0f9fc320363c..fd3fd0ce122c 100644 --- a/drivers/spi/spi-sprd.c +++ b/drivers/spi/spi-sprd.c @@ -977,7 +977,7 @@ static int sprd_spi_probe(struct platform_device *pdev) goto err_rpm_put; } - ret = devm_spi_register_controller(&pdev->dev, sctlr); + ret = spi_register_controller(sctlr); if (ret) goto err_rpm_put; @@ -1008,7 +1008,9 @@ static void sprd_spi_remove(struct platform_device *pdev) if (ret < 0) dev_err(ss->dev, "failed to resume SPI controller\n"); - spi_controller_suspend(sctlr); + spi_controller_get(sctlr); + + spi_unregister_controller(sctlr); if (ret >= 0) { if (ss->dma.enable) @@ -1017,6 +1019,8 @@ static void sprd_spi_remove(struct platform_device *pdev) } pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + + spi_controller_put(sctlr); } static int __maybe_unused sprd_spi_runtime_suspend(struct device *dev) diff --git a/drivers/spi/spi-st-ssc4.c b/drivers/spi/spi-st-ssc4.c index b173ef70d77e..9c8099fe6e19 100644 --- a/drivers/spi/spi-st-ssc4.c +++ b/drivers/spi/spi-st-ssc4.c @@ -349,7 +349,7 @@ static int spi_st_probe(struct platform_device *pdev) platform_set_drvdata(pdev, host); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&pdev->dev, "Failed to register host\n"); goto rpm_disable; @@ -371,10 +371,16 @@ static void spi_st_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct spi_st *spi_st = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_disable(&pdev->dev); clk_disable_unprepare(spi_st->clk); + spi_controller_put(host); + pinctrl_pm_select_sleep_state(&pdev->dev); } diff --git a/drivers/spi/spi-stm32-ospi.c b/drivers/spi/spi-stm32-ospi.c index 38405f8f547f..4461c6e24b9e 100644 --- a/drivers/spi/spi-stm32-ospi.c +++ b/drivers/spi/spi-stm32-ospi.c @@ -469,11 +469,6 @@ static int stm32_ospi_send(struct spi_device *spi, const struct spi_mem_op *op) int timeout, err = 0, err_poll_status = 0; u8 cs = spi->chip_select[ffs(spi->cs_index_mask) - 1]; - dev_dbg(ospi->dev, "cmd:%#x mode:%d.%d.%d.%d addr:%#llx len:%#x\n", - op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, - op->dummy.buswidth, op->data.buswidth, - op->addr.val, op->data.nbytes); - cr = readl_relaxed(ospi->regs_base + OSPI_CR); cr &= ~CR_CSSEL; cr |= FIELD_PREP(CR_CSSEL, cs); diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index 33f211e159ef..be88e62075af 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -1659,7 +1659,7 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, ret = stm32_spi_prepare_rx_dma_mdma_chaining(spi, xfer, &rx_dma_conf, &rx_dma_desc, &rx_mdma_desc); if (ret) { /* RX DMA MDMA chaining not possible, fallback to DMA only */ - rx_dma_conf.peripheral_config = 0; + rx_dma_conf.peripheral_config = NULL; rx_dma_desc = NULL; } } @@ -2360,25 +2360,20 @@ static int stm32_spi_probe(struct platform_device *pdev) int ret; cfg = of_device_get_match_data(&pdev->dev); - if (!cfg) { - dev_err(&pdev->dev, "Failed to get match data for platform\n"); - return -ENODEV; - } + if (!cfg) + return dev_err_probe(&pdev->dev, -ENODEV, + "Failed to get match data for platform\n"); device_mode = of_property_read_bool(np, "spi-slave"); - if (!cfg->has_device_mode && device_mode) { - dev_err(&pdev->dev, "spi-slave not supported\n"); - return -EPERM; - } + if (!cfg->has_device_mode && device_mode) + return dev_err_probe(&pdev->dev, -EPERM, "spi-slave not supported\n"); if (device_mode) ctrl = devm_spi_alloc_target(&pdev->dev, sizeof(struct stm32_spi)); else ctrl = devm_spi_alloc_host(&pdev->dev, sizeof(struct stm32_spi)); - if (!ctrl) { - dev_err(&pdev->dev, "spi controller allocation failed\n"); - return -ENOMEM; - } + if (!ctrl) + return dev_err_probe(&pdev->dev, -ENOMEM, "spi controller allocation failed\n"); platform_set_drvdata(pdev, ctrl); spi = spi_controller_get_devdata(ctrl); @@ -2409,32 +2404,18 @@ static int stm32_spi_probe(struct platform_device *pdev) return ret; } - spi->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(spi->clk)) { - ret = PTR_ERR(spi->clk); - dev_err(&pdev->dev, "clk get failed: %d\n", ret); - return ret; - } + spi->clk = devm_clk_get_enabled(&pdev->dev, NULL); + if (IS_ERR(spi->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(spi->clk), "clk enabled failed\n"); - ret = clk_prepare_enable(spi->clk); - if (ret) { - dev_err(&pdev->dev, "clk enable failed: %d\n", ret); - return ret; - } spi->clk_rate = clk_get_rate(spi->clk); - if (!spi->clk_rate) { - dev_err(&pdev->dev, "clk rate = 0\n"); - ret = -EINVAL; - goto err_clk_disable; - } + if (!spi->clk_rate) + return dev_err_probe(&pdev->dev, -EINVAL, "clk rate = 0\n"); rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); if (rst) { - if (IS_ERR(rst)) { - ret = dev_err_probe(&pdev->dev, PTR_ERR(rst), - "failed to get reset\n"); - goto err_clk_disable; - } + if (IS_ERR(rst)) + return dev_err_probe(&pdev->dev, PTR_ERR(rst), "failed to get reset\n"); reset_control_assert(rst); udelay(2); @@ -2461,11 +2442,8 @@ static int stm32_spi_probe(struct platform_device *pdev) dev_dbg(spi->dev, "one message max size %d\n", spi->t_size_max); ret = spi->cfg->config(spi); - if (ret) { - dev_err(&pdev->dev, "controller configuration failed: %d\n", - ret); - goto err_clk_disable; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "controller configuration failed: %d\n", ret); ctrl->auto_runtime_pm = true; ctrl->bus_num = pdev->id; @@ -2490,8 +2468,7 @@ static int stm32_spi_probe(struct platform_device *pdev) dev_info(&pdev->dev, "tx dma disabled\n"); spi->dma_tx = NULL; } else { - dev_err_probe(&pdev->dev, ret, "failed to request tx dma channel\n"); - goto err_clk_disable; + return dev_err_probe(&pdev->dev, ret, "failed to request tx dma channel\n"); } } else { ctrl->dma_tx = spi->dma_tx; @@ -2505,7 +2482,7 @@ static int stm32_spi_probe(struct platform_device *pdev) spi->dma_rx = NULL; } else { dev_err_probe(&pdev->dev, ret, "failed to request rx dma channel\n"); - goto err_dma_release; + goto err_dma_tx_release; } } else { ctrl->dma_rx = spi->dma_rx; @@ -2574,13 +2551,11 @@ err_pool_free: if (spi->sram_pool) gen_pool_free(spi->sram_pool, (unsigned long)spi->sram_rx_buf, spi->sram_rx_buf_size); -err_dma_release: - if (spi->dma_tx) - dma_release_channel(spi->dma_tx); if (spi->dma_rx) dma_release_channel(spi->dma_rx); -err_clk_disable: - clk_disable_unprepare(spi->clk); +err_dma_tx_release: + if (spi->dma_tx) + dma_release_channel(spi->dma_tx); return ret; } @@ -2610,9 +2585,6 @@ static void stm32_spi_remove(struct platform_device *pdev) gen_pool_free(spi->sram_pool, (unsigned long)spi->sram_rx_buf, spi->sram_rx_buf_size); - clk_disable_unprepare(spi->clk); - - pinctrl_pm_select_sleep_state(&pdev->dev); } diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c index bfdf419a583c..b7fbb5270edb 100644 --- a/drivers/spi/spi-sun4i.c +++ b/drivers/spi/spi-sun4i.c @@ -504,7 +504,7 @@ static int sun4i_spi_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_idle(&pdev->dev); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&pdev->dev, "cannot register SPI host\n"); goto err_pm_disable; @@ -522,7 +522,15 @@ err_free_host: static void sun4i_spi_remove(struct platform_device *pdev) { + struct spi_controller *host = platform_get_drvdata(pdev); + + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_force_suspend(&pdev->dev); + + spi_controller_put(host); } static const struct of_device_id sun4i_spi_match[] = { diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c index 240e46f84f7b..5ac73d324d06 100644 --- a/drivers/spi/spi-sun6i.c +++ b/drivers/spi/spi-sun6i.c @@ -742,7 +742,7 @@ static int sun6i_spi_probe(struct platform_device *pdev) pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&pdev->dev, "cannot register SPI host\n"); goto err_pm_disable; @@ -768,12 +768,18 @@ static void sun6i_spi_remove(struct platform_device *pdev) { struct spi_controller *host = platform_get_drvdata(pdev); + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_force_suspend(&pdev->dev); if (host->dma_tx) dma_release_channel(host->dma_tx); if (host->dma_rx) dma_release_channel(host->dma_rx); + + spi_controller_put(host); } static const struct sun6i_spi_cfg sun6i_a31_spi_cfg = { diff --git a/drivers/spi/spi-sunplus-sp7021.c b/drivers/spi/spi-sunplus-sp7021.c index 789b092fe8c0..35601212fb78 100644 --- a/drivers/spi/spi-sunplus-sp7021.c +++ b/drivers/spi/spi-sunplus-sp7021.c @@ -389,11 +389,6 @@ static int sp7021_spi_target_transfer_one(struct spi_controller *ctlr, struct sp return ret; } -static void sp7021_spi_disable_unprepare(void *data) -{ - clk_disable_unprepare(data); -} - static void sp7021_spi_reset_control_assert(void *data) { reset_control_assert(data); @@ -460,7 +455,7 @@ static int sp7021_spi_controller_probe(struct platform_device *pdev) if (pspim->s_irq < 0) return pspim->s_irq; - pspim->spi_clk = devm_clk_get(dev, NULL); + pspim->spi_clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(pspim->spi_clk)) return dev_err_probe(dev, PTR_ERR(pspim->spi_clk), "clk get fail\n"); @@ -468,14 +463,6 @@ static int sp7021_spi_controller_probe(struct platform_device *pdev) if (IS_ERR(pspim->rstc)) return dev_err_probe(dev, PTR_ERR(pspim->rstc), "rst get fail\n"); - ret = clk_prepare_enable(pspim->spi_clk); - if (ret) - return dev_err_probe(dev, ret, "failed to enable clk\n"); - - ret = devm_add_action_or_reset(dev, sp7021_spi_disable_unprepare, pspim->spi_clk); - if (ret) - return ret; - ret = reset_control_deassert(pspim->rstc); if (ret) return dev_err_probe(dev, ret, "failed to deassert reset\n"); diff --git a/drivers/spi/spi-synquacer.c b/drivers/spi/spi-synquacer.c index d0a875249910..290c439897c4 100644 --- a/drivers/spi/spi-synquacer.c +++ b/drivers/spi/spi-synquacer.c @@ -716,7 +716,7 @@ static int synquacer_spi_probe(struct platform_device *pdev) pm_runtime_set_active(sspi->dev); pm_runtime_enable(sspi->dev); - ret = devm_spi_register_controller(sspi->dev, host); + ret = spi_register_controller(host); if (ret) goto disable_pm; @@ -737,9 +737,15 @@ static void synquacer_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct synquacer_spi *sspi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_disable(sspi->dev); clk_disable_unprepare(sspi->clk); + + spi_controller_put(host); } static int __maybe_unused synquacer_spi_suspend(struct device *dev) diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 848cb6836bd5..b8b0ebe0fe93 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -1415,7 +1415,7 @@ static int tegra_spi_probe(struct platform_device *pdev) goto exit_pm_disable; } - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret < 0) { dev_err(&pdev->dev, "can not register to host err %d\n", ret); goto exit_free_irq; @@ -1441,6 +1441,10 @@ static void tegra_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct tegra_spi_data *tspi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + free_irq(tspi->irq, tspi); if (tspi->tx_dma_chan) @@ -1452,6 +1456,8 @@ static void tegra_spi_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) tegra_spi_runtime_suspend(&pdev->dev); + + spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index d9d536d7f7b6..9256729f2d49 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -505,7 +505,7 @@ static int tegra_sflash_probe(struct platform_device *pdev) tegra_sflash_writel(tsd, tsd->def_command_reg, SPI_COMMAND); pm_runtime_put(&pdev->dev); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret < 0) { dev_err(&pdev->dev, "can not register to host err %d\n", ret); goto exit_pm_disable; @@ -528,11 +528,17 @@ static void tegra_sflash_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct tegra_sflash_data *tsd = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + free_irq(tsd->irq, tsd); pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) tegra_sflash_runtime_suspend(&pdev->dev); + + spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index 8c608abd6076..c15c076295cd 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -1007,7 +1007,7 @@ static int tegra_slink_probe(struct platform_device *pdev) cdata = of_device_get_match_data(&pdev->dev); - host = spi_alloc_host(&pdev->dev, sizeof(*tspi)); + host = devm_spi_alloc_host(&pdev->dev, sizeof(*tspi)); if (!host) { dev_err(&pdev->dev, "host allocation failed\n"); return -ENOMEM; @@ -1034,37 +1034,34 @@ static int tegra_slink_probe(struct platform_device *pdev) host->max_speed_hz = 25000000; /* 25MHz */ tspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r); - if (IS_ERR(tspi->base)) { - ret = PTR_ERR(tspi->base); - goto exit_free_host; - } + if (IS_ERR(tspi->base)) + return PTR_ERR(tspi->base); + tspi->phys = r->start; /* disabled clock may cause interrupt storm upon request */ tspi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(tspi->clk)) { ret = PTR_ERR(tspi->clk); - dev_err(&pdev->dev, "Can not get clock %d\n", ret); - goto exit_free_host; + return dev_err_probe(&pdev->dev, ret, "Can not get clock\n"); } tspi->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi"); if (IS_ERR(tspi->rst)) { - dev_err(&pdev->dev, "can not get reset\n"); ret = PTR_ERR(tspi->rst); - goto exit_free_host; + return dev_err_probe(&pdev->dev, ret, "can not get reset\n"); } ret = devm_tegra_core_dev_init_opp_table_common(&pdev->dev); if (ret) - goto exit_free_host; + return ret; tspi->max_buf_size = SLINK_FIFO_DEPTH << 2; tspi->dma_buf_size = DEFAULT_SPI_DMA_BUF_LEN; ret = tegra_slink_init_dma_param(tspi, true); if (ret < 0) - goto exit_free_host; + return ret; ret = tegra_slink_init_dma_param(tspi, false); if (ret < 0) goto exit_rx_dma_free; @@ -1125,14 +1122,13 @@ exit_pm_disable: tegra_slink_deinit_dma_param(tspi, false); exit_rx_dma_free: tegra_slink_deinit_dma_param(tspi, true); -exit_free_host: - spi_controller_put(host); + return ret; } static void tegra_slink_remove(struct platform_device *pdev) { - struct spi_controller *host = spi_controller_get(platform_get_drvdata(pdev)); + struct spi_controller *host = platform_get_drvdata(pdev); struct tegra_slink_data *tspi = spi_controller_get_devdata(host); spi_unregister_controller(host); @@ -1146,8 +1142,6 @@ static void tegra_slink_remove(struct platform_device *pdev) if (tspi->rx_dma_chan) tegra_slink_deinit_dma_param(tspi, true); - - spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c index 7ea5aa993596..db28dd556484 100644 --- a/drivers/spi/spi-tegra210-quad.c +++ b/drivers/spi/spi-tegra210-quad.c @@ -1000,7 +1000,7 @@ static int tegra_qspi_setup(struct spi_device *spi) spin_unlock_irqrestore(&tqspi->lock, flags); - pm_runtime_put(tqspi->dev); + pm_runtime_put_autosuspend(tqspi->dev); return 0; } @@ -1223,7 +1223,7 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, (&tqspi->xfer_completion, QSPI_DMA_TIMEOUT); - if (WARN_ON_ONCE(ret == 0)) { + if (ret == 0) { /* * Check if hardware completed the transfer * even though interrupt was lost or delayed. @@ -1232,6 +1232,7 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, ret = tegra_qspi_handle_timeout(tqspi); if (ret < 0) { /* Real timeout - clean up and fail */ + WARN_ON_ONCE(1); dev_err(tqspi->dev, "transfer timeout\n"); /* Abort transfer by resetting pio/dma bit */ @@ -1340,7 +1341,7 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, ret = wait_for_completion_timeout(&tqspi->xfer_completion, QSPI_DMA_TIMEOUT); - if (WARN_ON(ret == 0)) { + if (ret == 0) { /* * Check if hardware completed the transfer even though * interrupt was lost or delayed. If so, process the @@ -1349,6 +1350,7 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, ret = tegra_qspi_handle_timeout(tqspi); if (ret < 0) { /* Real timeout - clean up and fail */ + WARN_ON(1); dev_err(tqspi->dev, "transfer timeout\n"); if (tqspi->is_curr_dma_xfer) @@ -1765,6 +1767,14 @@ static int tegra_qspi_probe(struct platform_device *pdev) init_completion(&tqspi->rx_dma_complete); init_completion(&tqspi->xfer_completion); + /* + * Set autosuspend delay to 500ms. Testing shows this value eliminates + * suspend/resume overhead during burst operations while allowing quick + * suspension during idle. For longer operations, the overhead is negligible. + */ + pm_runtime_set_autosuspend_delay(&pdev->dev, 500); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(&pdev->dev); ret = pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) { @@ -1781,7 +1791,7 @@ static int tegra_qspi_probe(struct platform_device *pdev) tqspi->spi_cs_timing2 = tegra_qspi_readl(tqspi, QSPI_CS_TIMING2); tqspi->def_command2_reg = tegra_qspi_readl(tqspi, QSPI_COMMAND2); - pm_runtime_put(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); ret = request_threaded_irq(tqspi->irq, NULL, tegra_qspi_isr_thread, IRQF_ONESHOT, @@ -1802,6 +1812,7 @@ static int tegra_qspi_probe(struct platform_device *pdev) exit_free_irq: free_irq(qspi_irq, tqspi); exit_pm_disable: + pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_force_suspend(&pdev->dev); tegra_qspi_deinit_dma(tqspi); return ret; @@ -1814,6 +1825,7 @@ static void tegra_qspi_remove(struct platform_device *pdev) spi_unregister_controller(host); free_irq(tqspi->irq, tqspi); + pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_force_suspend(&pdev->dev); tegra_qspi_deinit_dma(tqspi); } @@ -1839,7 +1851,7 @@ static int __maybe_unused tegra_qspi_resume(struct device *dev) tegra_qspi_writel(tqspi, tqspi->command1_reg, QSPI_COMMAND1); tegra_qspi_writel(tqspi, tqspi->def_command2_reg, QSPI_COMMAND2); - pm_runtime_put(dev); + pm_runtime_put_autosuspend(dev); return spi_controller_resume(host); } diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index d1d880a8ed7d..1fbd710d616f 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -888,7 +888,7 @@ no_dma: qspi->mmap_enabled = false; qspi->current_cs = -1; - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (!ret) return 0; @@ -903,19 +903,17 @@ free_host: static void ti_qspi_remove(struct platform_device *pdev) { struct ti_qspi *qspi = platform_get_drvdata(pdev); - int rc; - rc = spi_controller_suspend(qspi->host); - if (rc) { - dev_alert(&pdev->dev, "spi_controller_suspend() failed (%pe)\n", - ERR_PTR(rc)); - return; - } + spi_controller_get(qspi->host); + + spi_unregister_controller(qspi->host); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); ti_qspi_dma_cleanup(qspi); + + spi_controller_put(qspi->host); } static const struct dev_pm_ops ti_qspi_pm_ops = { diff --git a/drivers/spi/spi-uniphier.c b/drivers/spi/spi-uniphier.c index 9e1d364a6198..eac6c3e8908b 100644 --- a/drivers/spi/spi-uniphier.c +++ b/drivers/spi/spi-uniphier.c @@ -666,28 +666,24 @@ static int uniphier_spi_probe(struct platform_device *pdev) } priv->base_dma_addr = res->start; - priv->clk = devm_clk_get(&pdev->dev, NULL); + priv->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(priv->clk)) { dev_err(&pdev->dev, "failed to get clock\n"); ret = PTR_ERR(priv->clk); goto out_host_put; } - ret = clk_prepare_enable(priv->clk); - if (ret) - goto out_host_put; - irq = platform_get_irq(pdev, 0); if (irq < 0) { ret = irq; - goto out_disable_clk; + goto out_host_put; } ret = devm_request_irq(&pdev->dev, irq, uniphier_spi_handler, 0, "uniphier-spi", priv); if (ret) { dev_err(&pdev->dev, "failed to request IRQ\n"); - goto out_disable_clk; + goto out_host_put; } init_completion(&priv->xfer_done); @@ -716,7 +712,7 @@ static int uniphier_spi_probe(struct platform_device *pdev) if (IS_ERR_OR_NULL(host->dma_tx)) { if (PTR_ERR(host->dma_tx) == -EPROBE_DEFER) { ret = -EPROBE_DEFER; - goto out_disable_clk; + goto out_host_put; } host->dma_tx = NULL; dma_tx_burst = INT_MAX; @@ -750,7 +746,7 @@ static int uniphier_spi_probe(struct platform_device *pdev) host->max_dma_len = min(dma_tx_burst, dma_rx_burst); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) goto out_release_dma; @@ -766,9 +762,6 @@ out_release_dma: host->dma_tx = NULL; } -out_disable_clk: - clk_disable_unprepare(priv->clk); - out_host_put: spi_controller_put(host); return ret; @@ -777,14 +770,17 @@ out_host_put: static void uniphier_spi_remove(struct platform_device *pdev) { struct spi_controller *host = platform_get_drvdata(pdev); - struct uniphier_spi_priv *priv = spi_controller_get_devdata(host); + + spi_controller_get(host); + + spi_unregister_controller(host); if (host->dma_tx) dma_release_channel(host->dma_tx); if (host->dma_rx) dma_release_channel(host->dma_rx); - clk_disable_unprepare(priv->clk); + spi_controller_put(host); } static const struct of_device_id uniphier_spi_match[] = { diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c index af252500195c..406fd9d5337e 100644 --- a/drivers/spi/spi-zynq-qspi.c +++ b/drivers/spi/spi-zynq-qspi.c @@ -643,7 +643,7 @@ static int zynq_qspi_probe(struct platform_device *pdev) xqspi = spi_controller_get_devdata(ctlr); xqspi->dev = dev; - platform_set_drvdata(pdev, xqspi); + platform_set_drvdata(pdev, ctlr); xqspi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(xqspi->regs)) { ret = PTR_ERR(xqspi->regs); @@ -702,9 +702,9 @@ static int zynq_qspi_probe(struct platform_device *pdev) /* QSPI controller initializations */ zynq_qspi_init_hw(xqspi, ctlr->num_chipselect); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret) { - dev_err(&pdev->dev, "devm_spi_register_controller failed\n"); + dev_err(&pdev->dev, "failed to register controller\n"); goto remove_ctlr; } @@ -728,9 +728,16 @@ remove_ctlr: */ static void zynq_qspi_remove(struct platform_device *pdev) { - struct zynq_qspi *xqspi = platform_get_drvdata(pdev); + struct spi_controller *ctlr = platform_get_drvdata(pdev); + struct zynq_qspi *xqspi = spi_controller_get_devdata(ctlr); + + spi_controller_get(ctlr); + + spi_unregister_controller(ctlr); zynq_qspi_write(xqspi, ZYNQ_QSPI_ENABLE_OFFSET, 0); + + spi_controller_put(ctlr); } static const struct of_device_id zynq_qspi_of_match[] = { diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index 502fd5eccc83..f9a1427dabad 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -1324,7 +1324,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) ctlr->dev.of_node = np; ctlr->auto_runtime_pm = true; - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret) { dev_err(&pdev->dev, "spi_register_controller failed\n"); goto clk_dis_all; @@ -1362,6 +1362,8 @@ static void zynqmp_qspi_remove(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); + spi_unregister_controller(xqspi->ctlr); + zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, 0x0); pm_runtime_disable(&pdev->dev); diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 91dd831d2d3b..7001f5dce8bd 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -89,25 +89,22 @@ static ssize_t driver_override_show(struct device *dev, } static DEVICE_ATTR_RW(driver_override); -static struct spi_statistics __percpu *spi_alloc_pcpu_stats(struct device *dev) +static struct spi_statistics __percpu *spi_alloc_pcpu_stats(void) { struct spi_statistics __percpu *pcpu_stats; + int cpu; - if (dev) - pcpu_stats = devm_alloc_percpu(dev, struct spi_statistics); - else - pcpu_stats = alloc_percpu_gfp(struct spi_statistics, GFP_KERNEL); - - if (pcpu_stats) { - int cpu; + pcpu_stats = alloc_percpu_gfp(struct spi_statistics, GFP_KERNEL); + if (!pcpu_stats) + return NULL; - for_each_possible_cpu(cpu) { - struct spi_statistics *stat; + for_each_possible_cpu(cpu) { + struct spi_statistics *stat; - stat = per_cpu_ptr(pcpu_stats, cpu); - u64_stats_init(&stat->syncp); - } + stat = per_cpu_ptr(pcpu_stats, cpu); + u64_stats_init(&stat->syncp); } + return pcpu_stats; } @@ -569,7 +566,7 @@ struct spi_device *spi_alloc_device(struct spi_controller *ctlr) return NULL; } - spi->pcpu_statistics = spi_alloc_pcpu_stats(NULL); + spi->pcpu_statistics = spi_alloc_pcpu_stats(); if (!spi->pcpu_statistics) { kfree(spi); spi_controller_put(ctlr); @@ -636,12 +633,26 @@ static inline int spi_dev_check_cs(struct device *dev, return 0; } +struct spi_dev_check_info { + struct spi_device *new_spi; + struct spi_device *parent; /* set for ancillary devices */ +}; + static int spi_dev_check(struct device *dev, void *data) { struct spi_device *spi = to_spi_device(dev); - struct spi_device *new_spi = data; + struct spi_dev_check_info *info = data; + struct spi_device *new_spi = info->new_spi; int status, idx; + /* + * When registering an ancillary device, skip checking against the + * parent device since the ancillary is intentionally using one of + * the parent's chip selects. + */ + if (info->parent && spi == info->parent) + return 0; + if (spi->controller == new_spi->controller) { for (idx = 0; idx < spi->num_chipselect; idx++) { status = spi_dev_check_cs(dev, spi, idx, new_spi, 0); @@ -658,10 +669,11 @@ static void spi_cleanup(struct spi_device *spi) spi->controller->cleanup(spi); } -static int __spi_add_device(struct spi_device *spi) +static int __spi_add_device(struct spi_device *spi, struct spi_device *parent) { struct spi_controller *ctlr = spi->controller; struct device *dev = ctlr->dev.parent; + struct spi_dev_check_info check_info; int status, idx; u8 cs; @@ -705,7 +717,9 @@ static int __spi_add_device(struct spi_device *spi) * chipselect **BEFORE** we call setup(), else we'll trash * its configuration. */ - status = bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check); + check_info.new_spi = spi; + check_info.parent = parent; + status = bus_for_each_dev(&spi_bus_type, NULL, &check_info, spi_dev_check); if (status) return status; @@ -767,7 +781,7 @@ int spi_add_device(struct spi_device *spi) spi_dev_set_name(spi); mutex_lock(&ctlr->add_lock); - status = __spi_add_device(spi); + status = __spi_add_device(spi, NULL); mutex_unlock(&ctlr->add_lock); return status; } @@ -2710,8 +2724,8 @@ struct spi_device *spi_new_ancillary_device(struct spi_device *spi, WARN_ON(!mutex_is_locked(&ctlr->add_lock)); - /* Register the new device */ - rc = __spi_add_device(ancillary); + /* Register the new device, passing the parent to skip CS conflict check */ + rc = __spi_add_device(ancillary, spi); if (rc) { dev_err(&spi->dev, "failed to register ancillary device\n"); goto err_out; @@ -2725,6 +2739,46 @@ err_out: } EXPORT_SYMBOL_GPL(spi_new_ancillary_device); +static void devm_spi_unregister_device(void *spi) +{ + spi_unregister_device(spi); +} + +/** + * devm_spi_new_ancillary_device() - Register managed ancillary SPI device + * @spi: Pointer to the main SPI device registering the ancillary device + * @chip_select: Chip Select of the ancillary device + * + * Register an ancillary SPI device; for example some chips have a chip-select + * for normal device usage and another one for setup/firmware upload. + * + * This is the managed version of spi_new_ancillary_device(). The ancillary + * device will be unregistered automatically when the parent SPI device is + * unregistered. + * + * This may only be called from main SPI device's probe routine. + * + * Return: Pointer to new ancillary device on success; ERR_PTR on failure + */ +struct spi_device *devm_spi_new_ancillary_device(struct spi_device *spi, + u8 chip_select) +{ + struct spi_device *ancillary; + int ret; + + ancillary = spi_new_ancillary_device(spi, chip_select); + if (IS_ERR(ancillary)) + return ancillary; + + ret = devm_add_action_or_reset(&spi->dev, devm_spi_unregister_device, + ancillary); + if (ret) + return ERR_PTR(ret); + + return ancillary; +} +EXPORT_SYMBOL_GPL(devm_spi_new_ancillary_device); + #ifdef CONFIG_ACPI struct acpi_spi_lookup { struct spi_controller *ctlr; @@ -3189,7 +3243,7 @@ struct spi_controller *__spi_alloc_controller(struct device *dev, if (!ctlr) return NULL; - ctlr->pcpu_statistics = spi_alloc_pcpu_stats(NULL); + ctlr->pcpu_statistics = spi_alloc_pcpu_stats(); if (!ctlr->pcpu_statistics) { kfree(ctlr); return NULL; @@ -3386,8 +3440,8 @@ static int spi_controller_id_alloc(struct spi_controller *ctlr, int start, int e * device identification, boards need configuration tables telling which * chip is at which address. * - * This must be called from context that can sleep. It returns zero on - * success, else a negative error code (dropping the controller's refcount). + * This must be called from context that can sleep. + * * After a successful return, the caller is responsible for calling * spi_unregister_controller(). * @@ -3521,7 +3575,8 @@ static void devm_spi_unregister_controller(void *ctlr) * Context: can sleep * * Register a SPI device as with spi_register_controller() which will - * automatically be unregistered and freed. + * automatically be unregistered (and freed unless it has been allocated using + * devm_spi_alloc_host/target()). * * Return: zero on success, else a negative error code. */ @@ -3566,7 +3621,8 @@ static int __unregister(struct device *dev, void *null) * * This must be called from context that can sleep. * - * Note that this function also drops a reference to the controller. + * Note that this function also drops a reference to the controller unless it + * has been allocated using devm_spi_alloc_host/target(). */ void spi_unregister_controller(struct spi_controller *ctlr) { @@ -4232,12 +4288,7 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) * SPI transfer length should be multiple of SPI word size * where SPI word size should be power-of-two multiple. */ - if (xfer->bits_per_word <= 8) - w_size = 1; - else if (xfer->bits_per_word <= 16) - w_size = 2; - else - w_size = 4; + w_size = spi_bpw_to_bytes(xfer->bits_per_word); /* No partial transfers accepted */ if (xfer->len % w_size) diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h index 5774e554c0f0..c8e207522223 100644 --- a/include/linux/spi/spi-mem.h +++ b/include/linux/spi/spi-mem.h @@ -28,6 +28,14 @@ .dtr = true, \ } +#define SPI_MEM_DTR_OP_PACKED_CMD(__opcode, __addr, __buswidth) \ + { \ + .nbytes = 2, \ + .opcode = __opcode << 8 | __addr, \ + .buswidth = __buswidth, \ + .dtr = true, \ + } + #define SPI_MEM_OP_ADDR(__nbytes, __val, __buswidth) \ { \ .nbytes = __nbytes, \ @@ -130,11 +138,13 @@ enum spi_mem_data_dir { /** * struct spi_mem_op - describes a SPI memory operation + * @cmd: the complete command * @cmd.nbytes: number of opcode bytes (only 1 or 2 are valid). The opcode is * sent MSB-first. * @cmd.buswidth: number of IO lines used to transmit the command * @cmd.opcode: operation opcode * @cmd.dtr: whether the command opcode should be sent in DTR mode or not + * @addr: the address attributes * @addr.nbytes: number of address bytes to send. Can be zero if the operation * does not need to send an address * @addr.buswidth: number of IO lines used to transmit the address cycles @@ -143,10 +153,12 @@ enum spi_mem_data_dir { * Note that only @addr.nbytes are taken into account in this * address value, so users should make sure the value fits in the * assigned number of bytes. + * @dummy: data for dummy operation * @dummy.nbytes: number of dummy bytes to send after an opcode or address. Can * be zero if the operation does not require dummy bytes * @dummy.buswidth: number of IO lanes used to transmit the dummy bytes * @dummy.dtr: whether the dummy bytes should be sent in DTR mode or not + * @data: the data attributes * @data.buswidth: number of IO lanes used to send/receive the data * @data.dtr: whether the data should be sent in DTR mode or not * @data.ecc: whether error correction is required or not @@ -273,7 +285,7 @@ struct spi_mem { }; /** - * struct spi_mem_set_drvdata() - attach driver private data to a SPI mem + * spi_mem_set_drvdata() - attach driver private data to a SPI mem * device * @mem: memory device * @data: data to attach to the memory device @@ -284,7 +296,7 @@ static inline void spi_mem_set_drvdata(struct spi_mem *mem, void *data) } /** - * struct spi_mem_get_drvdata() - get driver private data attached to a SPI mem + * spi_mem_get_drvdata() - get driver private data attached to a SPI mem * device * @mem: memory device * diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 0dc671c07d3a..7587b1c5d7ec 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -382,6 +382,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) } extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 chip_select); +extern struct spi_device *devm_spi_new_ancillary_device(struct spi_device *spi, u8 chip_select); /* Use a define to avoid include chaining to get THIS_MODULE */ #define spi_register_driver(driver) \ |
