From b3c15f78befc6031de7d5bcb683d37018b20c425 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Thu, 18 Feb 2021 15:09:50 +0200 Subject: [PATCH 001/113] spi: spi-ti-qspi: Free DMA resources Release the RX channel and free the dma coherent memory when devm_spi_register_master() fails. Fixes: 5720ec0a6d26 ("spi: spi-ti-qspi: Add DMA support for QSPI mmap read") Cc: stable@vger.kernel.org Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20210218130950.90155-1-tudor.ambarus@microchip.com Signed-off-by: Mark Brown --- drivers/spi/spi-ti-qspi.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 9417385c092175..e06aafe169e0cb 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -733,6 +733,17 @@ static int ti_qspi_runtime_resume(struct device *dev) return 0; } +static void ti_qspi_dma_cleanup(struct ti_qspi *qspi) +{ + if (qspi->rx_bb_addr) + dma_free_coherent(qspi->dev, QSPI_DMA_BUFFER_SIZE, + qspi->rx_bb_addr, + qspi->rx_bb_dma_addr); + + if (qspi->rx_chan) + dma_release_channel(qspi->rx_chan); +} + static const struct of_device_id ti_qspi_match[] = { {.compatible = "ti,dra7xxx-qspi" }, {.compatible = "ti,am4372-qspi" }, @@ -886,6 +897,8 @@ static int ti_qspi_probe(struct platform_device *pdev) if (!ret) return 0; + ti_qspi_dma_cleanup(qspi); + pm_runtime_disable(&pdev->dev); free_master: spi_master_put(master); @@ -904,12 +917,7 @@ static int ti_qspi_remove(struct platform_device *pdev) pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - if (qspi->rx_bb_addr) - dma_free_coherent(qspi->dev, QSPI_DMA_BUFFER_SIZE, - qspi->rx_bb_addr, - qspi->rx_bb_dma_addr); - if (qspi->rx_chan) - dma_release_channel(qspi->rx_chan); + ti_qspi_dma_cleanup(qspi); return 0; } From 73ae625da5c36300fccd809738e7c68f49ebce35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Tue, 23 Feb 2021 16:18:50 +0100 Subject: [PATCH 002/113] spi: bcm63xx-spi: fix pm_runtime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver sets auto_runtime_pm to true, but it doesn't call pm_runtime_enable(), which results in "Failed to power device" when PM support is enabled. Signed-off-by: Álvaro Fernández Rojas Link: https://lore.kernel.org/r/20210223151851.4110-2-noltari@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 96d075e633f432..d08bb7600150cc 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -593,11 +593,13 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS); + pm_runtime_enable(&pdev->dev); + /* register and we are done */ ret = devm_spi_register_master(dev, master); if (ret) { dev_err(dev, "spi register failed\n"); - goto out_clk_disable; + goto out_pm_disable; } dev_info(dev, "at %pr (irq %d, FIFOs size %d)\n", @@ -605,6 +607,8 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) return 0; +out_pm_disable: + pm_runtime_disable(&pdev->dev); out_clk_disable: clk_disable_unprepare(clk); out_err: From 216e8e80057a9f0b6366327881acf88eaf9f1fd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Tue, 23 Feb 2021 16:18:51 +0100 Subject: [PATCH 003/113] spi: bcm63xx-hsspi: fix pm_runtime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver sets auto_runtime_pm to true, but it doesn't call pm_runtime_enable(), which results in "Failed to power device" when PM support is enabled. Signed-off-by: Álvaro Fernández Rojas Link: https://lore.kernel.org/r/20210223151851.4110-3-noltari@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx-hsspi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index 1f08d7553f079c..b871fd810d8015 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -21,6 +21,7 @@ #include #include #include +#include #define HSSPI_GLOBAL_CTRL_REG 0x0 #define GLOBAL_CTRL_CS_POLARITY_SHIFT 0 @@ -439,13 +440,17 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) if (ret) goto out_put_master; + pm_runtime_enable(&pdev->dev); + /* register and we are done */ ret = devm_spi_register_master(dev, master); if (ret) - goto out_put_master; + goto out_pm_disable; return 0; +out_pm_disable: + pm_runtime_disable(&pdev->dev); out_put_master: spi_master_put(master); out_disable_pll_clk: From 1d309cd688a76fb733f0089d36dc630327b32d59 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Thu, 18 Feb 2021 15:09:50 +0200 Subject: [PATCH 004/113] spi: spi-ti-qspi: Free DMA resources Release the RX channel and free the dma coherent memory when devm_spi_register_master() fails. Fixes: 5720ec0a6d26 ("spi: spi-ti-qspi: Add DMA support for QSPI mmap read") Cc: stable@vger.kernel.org Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20210218130950.90155-1-tudor.ambarus@microchip.com Signed-off-by: Mark Brown --- drivers/spi/spi-ti-qspi.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 9417385c092175..e06aafe169e0cb 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -733,6 +733,17 @@ static int ti_qspi_runtime_resume(struct device *dev) return 0; } +static void ti_qspi_dma_cleanup(struct ti_qspi *qspi) +{ + if (qspi->rx_bb_addr) + dma_free_coherent(qspi->dev, QSPI_DMA_BUFFER_SIZE, + qspi->rx_bb_addr, + qspi->rx_bb_dma_addr); + + if (qspi->rx_chan) + dma_release_channel(qspi->rx_chan); +} + static const struct of_device_id ti_qspi_match[] = { {.compatible = "ti,dra7xxx-qspi" }, {.compatible = "ti,am4372-qspi" }, @@ -886,6 +897,8 @@ static int ti_qspi_probe(struct platform_device *pdev) if (!ret) return 0; + ti_qspi_dma_cleanup(qspi); + pm_runtime_disable(&pdev->dev); free_master: spi_master_put(master); @@ -904,12 +917,7 @@ static int ti_qspi_remove(struct platform_device *pdev) pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - if (qspi->rx_bb_addr) - dma_free_coherent(qspi->dev, QSPI_DMA_BUFFER_SIZE, - qspi->rx_bb_addr, - qspi->rx_bb_dma_addr); - if (qspi->rx_chan) - dma_release_channel(qspi->rx_chan); + ti_qspi_dma_cleanup(qspi); return 0; } From 2d13f2ff60732a7f7accc250da8856650beb0d6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Tue, 23 Feb 2021 16:18:50 +0100 Subject: [PATCH 005/113] spi: bcm63xx-spi: fix pm_runtime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver sets auto_runtime_pm to true, but it doesn't call pm_runtime_enable(), which results in "Failed to power device" when PM support is enabled. Signed-off-by: Álvaro Fernández Rojas Link: https://lore.kernel.org/r/20210223151851.4110-2-noltari@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 96d075e633f432..d08bb7600150cc 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -593,11 +593,13 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS); + pm_runtime_enable(&pdev->dev); + /* register and we are done */ ret = devm_spi_register_master(dev, master); if (ret) { dev_err(dev, "spi register failed\n"); - goto out_clk_disable; + goto out_pm_disable; } dev_info(dev, "at %pr (irq %d, FIFOs size %d)\n", @@ -605,6 +607,8 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) return 0; +out_pm_disable: + pm_runtime_disable(&pdev->dev); out_clk_disable: clk_disable_unprepare(clk); out_err: From fb8695e3749ee6f19e0b524ec6dd78b1f8a82586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Tue, 23 Feb 2021 16:18:51 +0100 Subject: [PATCH 006/113] spi: bcm63xx-hsspi: fix pm_runtime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver sets auto_runtime_pm to true, but it doesn't call pm_runtime_enable(), which results in "Failed to power device" when PM support is enabled. Signed-off-by: Álvaro Fernández Rojas Link: https://lore.kernel.org/r/20210223151851.4110-3-noltari@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx-hsspi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index 1f08d7553f079c..b871fd810d8015 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -21,6 +21,7 @@ #include #include #include +#include #define HSSPI_GLOBAL_CTRL_REG 0x0 #define GLOBAL_CTRL_CS_POLARITY_SHIFT 0 @@ -439,13 +440,17 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) if (ret) goto out_put_master; + pm_runtime_enable(&pdev->dev); + /* register and we are done */ ret = devm_spi_register_master(dev, master); if (ret) - goto out_put_master; + goto out_pm_disable; return 0; +out_pm_disable: + pm_runtime_disable(&pdev->dev); out_put_master: spi_master_put(master); out_disable_pll_clk: From 19e2132174583beb90c1bd3e9c842bc6d5c944d1 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Wed, 3 Mar 2021 17:08:36 +0100 Subject: [PATCH 007/113] spi: ath79: always call chipselect function spi-bitbang has to call the chipselect function on the ath79 SPI driver in order to communicate with the SPI slave device, as the ath79 SPI driver has three dedicated chipselect lines but can also be used with GPIOs for the CS lines. Fixes commit 4a07b8bcd503 ("spi: bitbang: Make chipselect callback optional") Signed-off-by: David Bauer Link: https://lore.kernel.org/r/20210303160837.165771-1-mail@david-bauer.net Signed-off-by: Mark Brown --- drivers/spi/spi-ath79.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index eb9a243e95265c..436327fb58de66 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -158,6 +158,7 @@ static int ath79_spi_probe(struct platform_device *pdev) master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); master->setup = spi_bitbang_setup; master->cleanup = spi_bitbang_cleanup; + master->flags = SPI_MASTER_GPIO_SS; if (pdata) { master->bus_num = pdata->bus_num; master->num_chipselect = pdata->num_chipselect; From ffb597b2bd3cd78b9bfb68f536743cd46dbb2cc4 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Wed, 3 Mar 2021 17:08:37 +0100 Subject: [PATCH 008/113] spi: ath79: remove spi-master setup and cleanup assignment This removes the assignment of setup and cleanup functions for the ath79 target. Assigning the setup-method will lead to 'setup_transfer' not being assigned in spi_bitbang_init. Because of this, performing any TX/RX operation will lead to a kernel oops. Also drop the redundant cleanup assignment, as it's also assigned in spi_bitbang_init. Signed-off-by: David Bauer Link: https://lore.kernel.org/r/20210303160837.165771-2-mail@david-bauer.net Signed-off-by: Mark Brown --- drivers/spi/spi-ath79.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index 436327fb58de66..98ace748cd986a 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -156,8 +156,6 @@ static int ath79_spi_probe(struct platform_device *pdev) master->use_gpio_descriptors = true; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); - master->setup = spi_bitbang_setup; - master->cleanup = spi_bitbang_cleanup; master->flags = SPI_MASTER_GPIO_SS; if (pdata) { master->bus_num = pdata->bus_num; From a0521f70aee008f8b574f13ebdf0010f2f90db62 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 3 Mar 2021 11:16:40 +0200 Subject: [PATCH 009/113] parport: Introduce module_parport_driver() helper macro Introduce module_parport_driver() helper macro to reduce boilerplate in the existing and new code. Signed-off-by: Andy Shevchenko Acked-by: Sudip Mukherjee Reviewed-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20210303091642.23929-2-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- include/linux/parport.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/include/linux/parport.h b/include/linux/parport.h index f981f794c8501e..1c16ffb8b908db 100644 --- a/include/linux/parport.h +++ b/include/linux/parport.h @@ -332,9 +332,19 @@ int __must_check __parport_register_driver(struct parport_driver *, __parport_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) /* Unregister a high-level driver. */ -extern void parport_unregister_driver (struct parport_driver *); void parport_unregister_driver(struct parport_driver *); +/** + * module_parport_driver() - Helper macro for registering a modular parport driver + * @__parport_driver: struct parport_driver to be used + * + * Helper macro for parport drivers which do not do anything special in module + * init and exit. This eliminates a lot of boilerplate. Each module may only + * use this macro once, and calling it replaces module_init() and module_exit(). + */ +#define module_parport_driver(__parport_driver) \ + module_driver(__parport_driver, parport_register_driver, parport_unregister_driver) + /* If parport_register_driver doesn't fit your needs, perhaps * parport_find_xxx does. */ extern struct parport *parport_find_number (int); From 8c7e98f74cebf22f693494c0a7fe9afe77bd6576 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 3 Mar 2021 11:16:41 +0200 Subject: [PATCH 010/113] spi: butterfly: Switch to use module_parport_driver() Switch to use module_parport_driver() to reduce boilerplate code. Note, device_initcall() is a default for module_init(). Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20210303091642.23929-3-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-butterfly.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/spi/spi-butterfly.c b/drivers/spi/spi-butterfly.c index 7e71a351f3b732..cceae816cebc21 100644 --- a/drivers/spi/spi-butterfly.c +++ b/drivers/spi/spi-butterfly.c @@ -317,18 +317,7 @@ static struct parport_driver butterfly_driver = { .detach = butterfly_detach, .devmodel = true, }; - -static int __init butterfly_init(void) -{ - return parport_register_driver(&butterfly_driver); -} -device_initcall(butterfly_init); - -static void __exit butterfly_exit(void) -{ - parport_unregister_driver(&butterfly_driver); -} -module_exit(butterfly_exit); +module_parport_driver(butterfly_driver); MODULE_DESCRIPTION("Parport Adapter driver for AVR Butterfly"); MODULE_LICENSE("GPL"); From 529bee9ed1b507d668dec8529f7a436e7bfd559e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 3 Mar 2021 11:16:42 +0200 Subject: [PATCH 011/113] spi: lm70llp: Switch to use module_parport_driver() Switch to use module_parport_driver() to reduce boilerplate code. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20210303091642.23929-4-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-lm70llp.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/spi/spi-lm70llp.c b/drivers/spi/spi-lm70llp.c index 174dba29b1ddeb..f914b8d2043e3e 100644 --- a/drivers/spi/spi-lm70llp.c +++ b/drivers/spi/spi-lm70llp.c @@ -320,18 +320,7 @@ static struct parport_driver spi_lm70llp_drv = { .detach = spi_lm70llp_detach, .devmodel = true, }; - -static int __init init_spi_lm70llp(void) -{ - return parport_register_driver(&spi_lm70llp_drv); -} -module_init(init_spi_lm70llp); - -static void __exit cleanup_spi_lm70llp(void) -{ - parport_unregister_driver(&spi_lm70llp_drv); -} -module_exit(cleanup_spi_lm70llp); +module_parport_driver(spi_lm70llp_drv); MODULE_AUTHOR("Kaiwan N Billimoria "); MODULE_DESCRIPTION( From abdc5db39d7202a4038bf9041ee8b3e1ea03bc0d Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Mon, 22 Feb 2021 03:32:43 +0100 Subject: [PATCH 012/113] spi: omap2-mcspi: Activate pinctrl idle state during runtime suspend Set the (optional) idle pinctrl state during runtime suspend. This is the same schema used in PL022 driver and can help with HW designs sharing the SPI lines for different purposes. Signed-off-by: Alexander Sverdlin Link: https://lore.kernel.org/r/20210222023243.491432-1-alexander.sverdlin@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index d4c9510af3931a..999c2273641642 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1327,6 +1327,17 @@ static int omap2_mcspi_controller_setup(struct omap2_mcspi *mcspi) return 0; } +static int omap_mcspi_runtime_suspend(struct device *dev) +{ + int error; + + error = pinctrl_pm_select_idle_state(dev); + if (error) + dev_warn(dev, "%s: failed to set pins: %i\n", __func__, error); + + return 0; +} + /* * When SPI wake up from off-mode, CS is in activate state. If it was in * inactive state when driver was suspend, then force it to inactive state at @@ -1338,6 +1349,11 @@ static int omap_mcspi_runtime_resume(struct device *dev) struct omap2_mcspi *mcspi = spi_master_get_devdata(master); struct omap2_mcspi_regs *ctx = &mcspi->ctx; struct omap2_mcspi_cs *cs; + int error; + + error = pinctrl_pm_select_default_state(dev); + if (error) + dev_warn(dev, "%s: failed to set pins: %i\n", __func__, error); /* McSPI: context restore */ mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, ctx->modulctrl); @@ -1566,11 +1582,6 @@ static int __maybe_unused omap2_mcspi_resume(struct device *dev) struct omap2_mcspi *mcspi = spi_master_get_devdata(master); int error; - error = pinctrl_pm_select_default_state(dev); - if (error) - dev_warn(mcspi->dev, "%s: failed to set pins: %i\n", - __func__, error); - error = spi_master_resume(master); if (error) dev_warn(mcspi->dev, "%s: master resume failed: %i\n", @@ -1582,7 +1593,8 @@ static int __maybe_unused omap2_mcspi_resume(struct device *dev) static const struct dev_pm_ops omap2_mcspi_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(omap2_mcspi_suspend, omap2_mcspi_resume) - .runtime_resume = omap_mcspi_runtime_resume, + .runtime_suspend = omap_mcspi_runtime_suspend, + .runtime_resume = omap_mcspi_runtime_resume, }; static struct platform_driver omap2_mcspi_driver = { From e50989527faeafb79f45a0f7529ba8e01dff1fff Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 26 Feb 2021 15:00:48 +0100 Subject: [PATCH 013/113] spi: rockchip: avoid objtool warning Building this file with clang leads to a an unreachable code path causing a warning from objtool: drivers/spi/spi-rockchip.o: warning: objtool: rockchip_spi_transfer_one()+0x2e0: sibling call from callable instruction with modified stack frame Change the unreachable() into an error return that can be handled if it ever happens, rather than silently crashing the kernel. Fixes: 65498c6ae241 ("spi: rockchip: support 4bit words") Signed-off-by: Arnd Bergmann Acked-by: Pratyush Yadav Link: https://lore.kernel.org/r/20210226140109.3477093-1-arnd@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-rockchip.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index 936ef54e09037b..0d75080da6480e 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -476,7 +476,7 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs, return 1; } -static void rockchip_spi_config(struct rockchip_spi *rs, +static int rockchip_spi_config(struct rockchip_spi *rs, struct spi_device *spi, struct spi_transfer *xfer, bool use_dma, bool slave_mode) { @@ -521,7 +521,9 @@ static void rockchip_spi_config(struct rockchip_spi *rs, * ctlr->bits_per_word_mask, so this shouldn't * happen */ - unreachable(); + dev_err(rs->dev, "unknown bits per word: %d\n", + xfer->bits_per_word); + return -EINVAL; } if (use_dma) { @@ -554,6 +556,8 @@ static void rockchip_spi_config(struct rockchip_spi *rs, */ writel_relaxed(2 * DIV_ROUND_UP(rs->freq, 2 * xfer->speed_hz), rs->regs + ROCKCHIP_SPI_BAUDR); + + return 0; } static size_t rockchip_spi_max_transfer_size(struct spi_device *spi) @@ -577,6 +581,7 @@ static int rockchip_spi_transfer_one( struct spi_transfer *xfer) { struct rockchip_spi *rs = spi_controller_get_devdata(ctlr); + int ret; bool use_dma; WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) && @@ -596,7 +601,9 @@ static int rockchip_spi_transfer_one( use_dma = ctlr->can_dma ? ctlr->can_dma(ctlr, spi, xfer) : false; - rockchip_spi_config(rs, spi, xfer, use_dma, ctlr->slave); + ret = rockchip_spi_config(rs, spi, xfer, use_dma, ctlr->slave); + if (ret) + return ret; if (use_dma) return rockchip_spi_prepare_dma(rs, ctlr, xfer); From 120a9e8155cbc0f50315f79a18cb03a1ee6f3211 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Thu, 18 Feb 2021 15:28:40 +0200 Subject: [PATCH 014/113] spi: atmel: Drop unused variable The DMA cap mask is no longer used since: commit 7758e390699f ("spi: atmel: remove compat for non DT board when requesting dma chan") Drop it now. Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20210218132840.131898-1-tudor.ambarus@microchip.com Signed-off-by: Mark Brown --- drivers/spi/spi-atmel.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index f429436082afae..7cd5fe00dfc113 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -506,10 +506,6 @@ static int atmel_spi_configure_dma(struct spi_master *master, struct device *dev = &as->pdev->dev; int err; - dma_cap_mask_t mask; - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - master->dma_tx = dma_request_chan(dev, "tx"); if (IS_ERR(master->dma_tx)) { err = PTR_ERR(master->dma_tx); From 87d62d8fa66622d75a76836ecc0fd2edbbcb38d3 Mon Sep 17 00:00:00 2001 From: Junlin Yang Date: Mon, 15 Feb 2021 19:04:25 +0800 Subject: [PATCH 015/113] spi: cadence-quadspi: add missing of_node_put Fix OF node leaks by calling of_node_put in for_each_available_child_of_node when the cycle returns. Generated by: scripts/coccinelle/iterators/for_each_child.cocci Signed-off-by: Junlin Yang Link: https://lore.kernel.org/r/20210215110425.1012-1-angkery@163.com Signed-off-by: Mark Brown --- drivers/spi/spi-cadence-quadspi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index 442cc7c53a47b9..14a712058fac68 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -1389,11 +1389,13 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi) ret = of_property_read_u32(np, "reg", &cs); if (ret) { dev_err(dev, "Couldn't determine chip select.\n"); + of_node_put(np); return ret; } if (cs >= CQSPI_MAX_CHIPSELECT) { dev_err(dev, "Chip select %d out of range.\n", cs); + of_node_put(np); return -EINVAL; } @@ -1402,8 +1404,10 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi) f_pdata->cs = cs; ret = cqspi_of_get_flash_pdata(pdev, f_pdata, np); - if (ret) + if (ret) { + of_node_put(np); return ret; + } } return 0; From 31e92cbfb9cd9f7dcb2c04858f6cdcb3cbca914f Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Tue, 2 Mar 2021 18:19:33 +0530 Subject: [PATCH 016/113] spi: spi-nxp-fspi: Add support for IP read only Add support for disabling AHB bus and read entire flash contents via IP bus only. Please note, this enables IP bus read using a quirk which can be enabled directly in device-type data or in existence of an errata where AHB bus may need to be disabled. Signed-off-by: Kuldeep Singh Link: https://lore.kernel.org/r/20210302124936.1972546-2-kuldeep.singh@nxp.com Signed-off-by: Mark Brown --- drivers/spi/spi-nxp-fspi.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index ab9035662717a3..829391e20e9202 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -311,6 +311,9 @@ #define NXP_FSPI_MAX_CHIPSELECT 4 #define NXP_FSPI_MIN_IOMAP SZ_4M +/* Access flash memory using IP bus only */ +#define FSPI_QUIRK_USE_IP_ONLY BIT(0) + struct nxp_fspi_devtype_data { unsigned int rxfifo; unsigned int txfifo; @@ -359,6 +362,11 @@ struct nxp_fspi { int selected; }; +static inline int needs_ip_only(struct nxp_fspi *f) +{ + return f->devtype_data->quirks & FSPI_QUIRK_USE_IP_ONLY; +} + /* * R/W functions for big- or little-endian registers: * The FSPI controller's endianness is independent of @@ -553,8 +561,8 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f, for (i = 0; i < ARRAY_SIZE(lutval); i++) fspi_writel(f, lutval[i], base + FSPI_LUT_REG(i)); - dev_dbg(f->dev, "CMD[%x] lutval[0:%x \t 1:%x \t 2:%x \t 3:%x]\n", - op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3]); + dev_dbg(f->dev, "CMD[%x] lutval[0:%x \t 1:%x \t 2:%x \t 3:%x], size: 0x%08x\n", + op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3], op->data.nbytes); /* lock LUT */ fspi_writel(f, FSPI_LUTKEY_VALUE, f->iobase + FSPI_LUTKEY); @@ -852,12 +860,14 @@ static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) nxp_fspi_prepare_lut(f, op); /* - * If we have large chunks of data, we read them through the AHB bus - * by accessing the mapped memory. In all other cases we use - * IP commands to access the flash. + * If we have large chunks of data, we read them through the AHB bus by + * accessing the mapped memory. In all other cases we use IP commands + * to access the flash. Read via AHB bus may be corrupted due to + * existence of an errata and therefore discard AHB read in such cases. */ if (op->data.nbytes > (f->devtype_data->rxfifo - 4) && - op->data.dir == SPI_MEM_DATA_IN) { + op->data.dir == SPI_MEM_DATA_IN && + !needs_ip_only(f)) { err = nxp_fspi_read_ahb(f, op); } else { if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT) @@ -888,6 +898,12 @@ static int nxp_fspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) op->data.nbytes = ALIGN_DOWN(op->data.nbytes, 8); } + /* Limit data bytes to RX FIFO in case of IP read only */ + if (op->data.dir == SPI_MEM_DATA_IN && + needs_ip_only(f) && + op->data.nbytes > f->devtype_data->rxfifo) + op->data.nbytes = f->devtype_data->rxfifo; + return 0; } From c791e3c31cb209e6f25a5f3767707d16c1a6069a Mon Sep 17 00:00:00 2001 From: Han Xu Date: Tue, 2 Mar 2021 18:19:35 +0530 Subject: [PATCH 017/113] spi: spi-nxp-fspi: Add imx8dxl driver support Add driver support for imx8dxl which support read through IP bus only and disable AHB bus due to an IC errata. Use the pre-defined quirk FSPI_QUIRK_USE_IP_ONLY directly in device-type data to disable AHB read. Signed-off-by: Han Xu Signed-off-by: Kuldeep Singh Link: https://lore.kernel.org/r/20210302124936.1972546-4-kuldeep.singh@nxp.com Signed-off-by: Mark Brown --- drivers/spi/spi-nxp-fspi.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index 829391e20e9202..80a9278d91edae 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -346,6 +346,14 @@ static const struct nxp_fspi_devtype_data imx8qxp_data = { .little_endian = true, /* little-endian */ }; +static const struct nxp_fspi_devtype_data imx8dxl_data = { + .rxfifo = SZ_512, /* (64 * 64 bits) */ + .txfifo = SZ_1K, /* (128 * 64 bits) */ + .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ + .quirks = FSPI_QUIRK_USE_IP_ONLY, + .little_endian = true, /* little-endian */ +}; + struct nxp_fspi { void __iomem *iobase; void __iomem *ahb_addr; @@ -1168,6 +1176,7 @@ static const struct of_device_id nxp_fspi_dt_ids[] = { { .compatible = "nxp,lx2160a-fspi", .data = (void *)&lx2160a_data, }, { .compatible = "nxp,imx8mm-fspi", .data = (void *)&imx8mm_data, }, { .compatible = "nxp,imx8qxp-fspi", .data = (void *)&imx8qxp_data, }, + { .compatible = "nxp,imx8dxl-fspi", .data = (void *)&imx8dxl_data, }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, nxp_fspi_dt_ids); From 82ce7d0e74b6f6d1fcddfc674e3f4d3d65965511 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Tue, 2 Mar 2021 18:19:36 +0530 Subject: [PATCH 018/113] spi: spi-nxp-fspi: Implement errata workaround for LS1028A Errata ERR050568 description says that "Flash access by FlexSPI AHB command may not work with platform frequency equal to 300 MHz" on LS1028A. By default, smaller length reads(equal to RX FIFO size) are done by IP bus and larger length reads using AHB bus. For adding errata workaround, use IP bus to read entire flash contents and disable AHB path when platform frequency is 300Mhz. Signed-off-by: Kuldeep Singh Link: https://lore.kernel.org/r/20210302124936.1972546-5-kuldeep.singh@nxp.com Signed-off-by: Mark Brown --- drivers/spi/spi-nxp-fspi.c | 79 +++++++++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index 80a9278d91edae..ed1e888c7ece41 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -49,8 +49,11 @@ #include #include #include +#include #include +#include +#include #include #include @@ -311,6 +314,8 @@ #define NXP_FSPI_MAX_CHIPSELECT 4 #define NXP_FSPI_MIN_IOMAP SZ_4M +#define DCFG_RCWSR1 0x100 + /* Access flash memory using IP bus only */ #define FSPI_QUIRK_USE_IP_ONLY BIT(0) @@ -322,7 +327,7 @@ struct nxp_fspi_devtype_data { bool little_endian; }; -static const struct nxp_fspi_devtype_data lx2160a_data = { +static struct nxp_fspi_devtype_data lx2160a_data = { .rxfifo = SZ_512, /* (64 * 64 bits) */ .txfifo = SZ_1K, /* (128 * 64 bits) */ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ @@ -330,7 +335,7 @@ static const struct nxp_fspi_devtype_data lx2160a_data = { .little_endian = true, /* little-endian */ }; -static const struct nxp_fspi_devtype_data imx8mm_data = { +static struct nxp_fspi_devtype_data imx8mm_data = { .rxfifo = SZ_512, /* (64 * 64 bits) */ .txfifo = SZ_1K, /* (128 * 64 bits) */ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ @@ -338,7 +343,7 @@ static const struct nxp_fspi_devtype_data imx8mm_data = { .little_endian = true, /* little-endian */ }; -static const struct nxp_fspi_devtype_data imx8qxp_data = { +static struct nxp_fspi_devtype_data imx8qxp_data = { .rxfifo = SZ_512, /* (64 * 64 bits) */ .txfifo = SZ_1K, /* (128 * 64 bits) */ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ @@ -346,7 +351,7 @@ static const struct nxp_fspi_devtype_data imx8qxp_data = { .little_endian = true, /* little-endian */ }; -static const struct nxp_fspi_devtype_data imx8dxl_data = { +static struct nxp_fspi_devtype_data imx8dxl_data = { .rxfifo = SZ_512, /* (64 * 64 bits) */ .txfifo = SZ_1K, /* (128 * 64 bits) */ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ @@ -364,7 +369,7 @@ struct nxp_fspi { struct clk *clk, *clk_en; struct device *dev; struct completion c; - const struct nxp_fspi_devtype_data *devtype_data; + struct nxp_fspi_devtype_data *devtype_data; struct mutex lock; struct pm_qos_request pm_qos_req; int selected; @@ -915,6 +920,59 @@ static int nxp_fspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) return 0; } +static void erratum_err050568(struct nxp_fspi *f) +{ + const struct soc_device_attribute ls1028a_soc_attr[] = { + { .family = "QorIQ LS1028A" }, + { /* sentinel */ } + }; + struct device_node *np; + struct regmap *map; + u32 val = 0, sysclk = 0; + int ret; + + /* Check for LS1028A family */ + if (!soc_device_match(ls1028a_soc_attr)) { + dev_dbg(f->dev, "Errata applicable only for LS1028A\n"); + return; + } + + /* Compute system clock frequency multiplier ratio */ + map = syscon_regmap_lookup_by_compatible("fsl,ls1028a-dcfg"); + if (IS_ERR(map)) { + dev_err(f->dev, "No syscon regmap\n"); + goto err; + } + + ret = regmap_read(map, DCFG_RCWSR1, &val); + if (ret < 0) + goto err; + + /* Strap bits 6:2 define SYS_PLL_RAT i.e frequency multiplier ratio */ + val = (val >> 2) & 0x1F; + WARN(val == 0, "Strapping is zero: Cannot determine ratio"); + + /* Compute system clock frequency */ + np = of_find_node_by_name(NULL, "clock-sysclk"); + if (!np) + goto err; + + if (of_property_read_u32(np, "clock-frequency", &sysclk)) + goto err; + + sysclk = (sysclk * val) / 1000000; /* Convert sysclk to Mhz */ + dev_dbg(f->dev, "val: 0x%08x, sysclk: %dMhz\n", val, sysclk); + + /* Use IP bus only if PLL is 300MHz */ + if (sysclk == 300) + f->devtype_data->quirks |= FSPI_QUIRK_USE_IP_ONLY; + + return; + +err: + dev_err(f->dev, "Errata cannot be executed. Read via IP bus may not work\n"); +} + static int nxp_fspi_default_setup(struct nxp_fspi *f) { void __iomem *base = f->iobase; @@ -933,6 +991,15 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f) if (ret) return ret; + /* + * ERR050568: Flash access by FlexSPI AHB command may not work with + * platform frequency equal to 300 MHz on LS1028A. + * LS1028A reuses LX2160A compatible entry. Make errata applicable for + * Layerscape LS1028A platform. + */ + if (of_device_is_compatible(f->dev->of_node, "nxp,lx2160a-fspi")) + erratum_err050568(f); + /* Reset the module */ /* w1c register, wait unit clear */ ret = fspi_readl_poll_tout(f, f->iobase + FSPI_MCR0, @@ -1036,7 +1103,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) f = spi_controller_get_devdata(ctlr); f->dev = dev; - f->devtype_data = device_get_match_data(dev); + f->devtype_data = (struct nxp_fspi_devtype_data *)device_get_match_data(dev); if (!f->devtype_data) { ret = -ENODEV; goto err_put_ctrl; From 32f298481add01d8c39e11a414bdc4d5037541ed Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Tue, 2 Mar 2021 18:19:34 +0530 Subject: [PATCH 019/113] spi: spi-nxp-fspi: Add imx8dxl support Add support for nxp,imx8dxl-fspi, do the bindings document. Signed-off-by: Kuldeep Singh Link: https://lore.kernel.org/r/20210302124936.1972546-3-kuldeep.singh@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/spi-nxp-fspi.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/spi/spi-nxp-fspi.txt b/Documentation/devicetree/bindings/spi/spi-nxp-fspi.txt index 7ac60d9fe3571f..df178d1b62e67a 100644 --- a/Documentation/devicetree/bindings/spi/spi-nxp-fspi.txt +++ b/Documentation/devicetree/bindings/spi/spi-nxp-fspi.txt @@ -4,6 +4,7 @@ Required properties: - compatible : Should be "nxp,lx2160a-fspi" "nxp,imx8qxp-fspi" "nxp,imx8mm-fspi" + "nxp,imx8dxl-fspi" - reg : First contains the register location and length, Second contains the memory mapping address and length From 260864f797f259143c52cd8b031a5727a3bedc5c Mon Sep 17 00:00:00 2001 From: Mason Zhang Date: Fri, 26 Feb 2021 19:01:10 +0800 Subject: [PATCH 020/113] spi: mt6779: update spi document this patch update spi document for MT6779 SOC. Signed-off-by: Mason Zhang Link: https://lore.kernel.org/r/20210226110109.30500-1-Mason.Zhang@mediatek.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/spi-mt65xx.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/spi/spi-mt65xx.txt b/Documentation/devicetree/bindings/spi/spi-mt65xx.txt index 9e43721fa7d65c..7bae7eef26c7ff 100644 --- a/Documentation/devicetree/bindings/spi/spi-mt65xx.txt +++ b/Documentation/devicetree/bindings/spi/spi-mt65xx.txt @@ -13,6 +13,7 @@ Required properties: - mediatek,mt8183-spi: for mt8183 platforms - "mediatek,mt8192-spi", "mediatek,mt6765-spi": for mt8192 platforms - "mediatek,mt8516-spi", "mediatek,mt2712-spi": for mt8516 platforms + - "mediatek,mt6779-spi", "mediatek,mt6765-spi": for mt6779 platforms - #address-cells: should be 1. From 31890269c0a031e704f995bbd39e1fd77a381207 Mon Sep 17 00:00:00 2001 From: Jay Fang Date: Thu, 4 Mar 2021 18:47:52 +0800 Subject: [PATCH 021/113] spi: cadence-quadspi: Silence shiftTooManyBitsSigned warning drivers/spi/spi-cadence-quadspi.c:267:18: warning: Shifting signed 32-bit value by 31 bits is undefined behaviour [shiftTooManyBitsSigned] return reg & (1 << CQSPI_REG_CONFIG_IDLE_LSB); ^ Reported-by: kernel test robot Reported-by: Dan Carpenter Signed-off-by: Jay Fang Link: https://lore.kernel.org/r/1614854872-8694-1-git-send-email-f.fangjian@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-cadence-quadspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index 14a712058fac68..e2d6ea8334235e 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -264,7 +264,7 @@ static bool cqspi_is_idle(struct cqspi_st *cqspi) { u32 reg = readl(cqspi->iobase + CQSPI_REG_CONFIG); - return reg & (1 << CQSPI_REG_CONFIG_IDLE_LSB); + return reg & (1UL << CQSPI_REG_CONFIG_IDLE_LSB); } static u32 cqspi_get_rd_sram_level(struct cqspi_st *cqspi) From 8d559a64f00b59af9cc02b803ff52f6e6880a651 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 12 Mar 2021 11:34:46 +0100 Subject: [PATCH 022/113] spi: stm32: drop devres version of spi_register_master A call to spi_unregister_master() triggers calling remove() for all the spi devices binded to the spi master. Some spi device driver requires to "talk" with the spi device during the remove(), e.g.: - a LCD panel like drivers/gpu/drm/panel/panel-lg-lg4573.c will turn off the backlighting sending a command over spi. This implies that the spi master must be fully functional when spi_unregister_master() is called, either if it is called explicitly in the master's remove() code or implicitly by the devres framework. Devres calls devres_release_all() to release all the resources "after" the remove() of the spi master driver (check code of __device_release_driver() in drivers/base/dd.c). If the spi master driver has an empty remove() then there would be no issue; the devres_release_all() will release everything in reverse order w.r.t. probe(). But if code in spi master driver remove() disables the spi or makes it not functional (like in this spi-stm32), then devres cannot be used safely for unregistering the spi master and the binded spi devices. Replace devm_spi_register_master() with spi_register_master() and add spi_unregister_master() as first action in remove(). Fixes: dcbe0d84dfa5 ("spi: add driver for STM32 SPI controller") Signed-off-by: Antonio Borneo Signed-off-by: Alain Volmat Link: https://lore.kernel.org/r/1615545286-5395-1-git-send-email-alain.volmat@foss.st.com Signed-off-by: Mark Brown --- drivers/spi/spi-stm32.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index 25c07646101190..97cf3a2d41802b 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -1929,7 +1929,7 @@ static int stm32_spi_probe(struct platform_device *pdev) pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); - ret = devm_spi_register_master(&pdev->dev, master); + ret = spi_register_master(master); if (ret) { dev_err(&pdev->dev, "spi master registration failed: %d\n", ret); @@ -1960,6 +1960,7 @@ static int stm32_spi_remove(struct platform_device *pdev) struct spi_master *master = platform_get_drvdata(pdev); struct stm32_spi *spi = spi_master_get_devdata(master); + spi_unregister_master(master); spi->cfg->disable(spi); if (master->dma_tx) From 93c941448994a728e691f7dce9ea6475e352b09c Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 8 Mar 2021 16:54:53 +0200 Subject: [PATCH 023/113] spi: spi-axi-spi-engine: remove usage of delay_usecs The 'delay_usecs' field was handled for backwards compatibility in case there were some users that still configured SPI delay transfers with this field. They should all be removed by now. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20210308145502.1075689-2-aardelean@deviqon.com Signed-off-by: Mark Brown --- drivers/spi/spi-axi-spi-engine.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index af86e6d6e16b9b..80c3e38f5c1b52 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -170,14 +170,10 @@ static void spi_engine_gen_sleep(struct spi_engine_program *p, bool dry, unsigned int t; int delay; - if (xfer->delay_usecs) { - delay = xfer->delay_usecs; - } else { - delay = spi_delay_to_ns(&xfer->delay, xfer); - if (delay < 0) - return; - delay /= 1000; - } + delay = spi_delay_to_ns(&xfer->delay, xfer); + if (delay < 0) + return; + delay /= 1000; if (delay == 0) return; From e7f2d4c6aacd0a2cded363bb14ef9b6e752798fd Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 8 Mar 2021 16:54:54 +0200 Subject: [PATCH 024/113] spi: bcm63xx-spi: don't check 'delay_usecs' field The 'delay_usecs' field was handled for backwards compatibility in case there were some users that still configured SPI delay transfers with this field. They should all be removed by now. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20210308145502.1075689-3-aardelean@deviqon.com Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index d08bb7600150cc..80fa0ef8909caa 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -369,7 +369,7 @@ static int bcm63xx_spi_transfer_one(struct spi_master *master, } /* CS will be deasserted directly after transfer */ - if (t->delay_usecs || t->delay.value) { + if (t->delay.value) { dev_err(&spi->dev, "unable to keep CS asserted after transfer\n"); status = -EINVAL; goto exit; From 66a3aadec42aa001c62ae9a637398d853880a02b Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 8 Mar 2021 16:54:55 +0200 Subject: [PATCH 025/113] spi: spi-bcm-qspi: replace 'delay_usecs' with 'delay.value' check The 'delay_usecs' field is going away. The replacement for it is the 'delay' field. So, we should check for 'delay.value' being non-zero. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20210308145502.1075689-4-aardelean@deviqon.com Signed-off-by: Mark Brown --- drivers/spi/spi-bcm-qspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index 707fe3a5d8effc..a78e56f566dd89 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -671,7 +671,7 @@ static int update_qspi_trans_byte_count(struct bcm_qspi *qspi, if (qt->byte >= qt->trans->len) { /* we're at the end of the spi_transfer */ /* in TX mode, need to pause for a delay or CS change */ - if (qt->trans->delay_usecs && + if (qt->trans->delay.value && (flags & TRANS_STATUS_BREAK_DELAY)) ret |= TRANS_STATUS_BREAK_DELAY; if (qt->trans->cs_change && From 506d1a1b441e058e318d8d81141295ff76927367 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 8 Mar 2021 16:54:56 +0200 Subject: [PATCH 026/113] spi: spi-sh: replace 'delay_usecs' with 'delay.value' in pr_debug The 'delay_usecs' field is going away. The replacement for it is the 'delay' field. So, we should print the 'delay.value' value instead. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20210308145502.1075689-5-aardelean@deviqon.com Signed-off-by: Mark Brown --- drivers/spi/spi-sh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-sh.c b/drivers/spi/spi-sh.c index 15123a8f41e1e7..45f30493533219 100644 --- a/drivers/spi/spi-sh.c +++ b/drivers/spi/spi-sh.c @@ -290,8 +290,8 @@ static void spi_sh_work(struct work_struct *work) list_for_each_entry(t, &mesg->transfers, transfer_list) { pr_debug("tx_buf = %p, rx_buf = %p\n", t->tx_buf, t->rx_buf); - pr_debug("len = %d, delay_usecs = %d\n", - t->len, t->delay_usecs); + pr_debug("len = %d, delay.value = %d\n", + t->len, t->delay.value); if (t->tx_buf) { ret = spi_sh_send(ss, mesg, t); From 7ca660f8212b2fbeb0f3133c3a6fa8805777a877 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 8 Mar 2021 16:54:57 +0200 Subject: [PATCH 027/113] spi: spi-tegra20-flash: don't check 'delay_usecs' field for spi transfer The 'delay_usecs' field was handled for backwards compatibility in case there were some users that still configured SPI delay transfers with this field. They should all be removed by now. So we can remove the 'delay_usecs' handling in this driver. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20210308145502.1075689-6-aardelean@deviqon.com Signed-off-by: Mark Brown --- drivers/spi/spi-tegra20-sflash.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index cfb7de73793763..2888d8a8dc6d5c 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -341,8 +341,7 @@ static int tegra_sflash_transfer_one_message(struct spi_master *master, goto exit; } msg->actual_length += xfer->len; - if (xfer->cs_change && - (xfer->delay_usecs || xfer->delay.value)) { + if (xfer->cs_change && xfer->delay.value) { tegra_sflash_writel(tsd, tsd->def_command_reg, SPI_COMMAND); spi_transfer_delay_exec(xfer); From 33a23423ca0a08b488791fc9d4ca53f4bea4e45b Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 8 Mar 2021 16:54:58 +0200 Subject: [PATCH 028/113] staging: greybus: spilib: use 'spi_delay_to_ns' for getting xfer delay The intent is the removal of the 'delay_usecs' field from the spi_transfer struct, as there is a 'delay' field that does the same thing. The spi_delay_to_ns() can be used to get the transfer delay. It works by using the 'delay_usecs' field first (if it is non-zero), and finally uses the 'delay' field. Since the 'delay_usecs' field is going away, this change makes use of the spi_delay_to_ns() function. This also means dividing the return value of the function by 1000, to convert it to microseconds. To prevent any potential faults when converting to microseconds and since the result of spi_delay_to_ns() is int, the delay is being computed in 32 bits and then clamped between 0 & U16_MAX. Signed-off-by: Alexandru Ardelean Acked-by: Viresh Kumar Acked-by: Rui Miguel Silva Acked-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20210308145502.1075689-7-aardelean@deviqon.com Signed-off-by: Mark Brown --- drivers/staging/greybus/spilib.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/staging/greybus/spilib.c b/drivers/staging/greybus/spilib.c index 672d540d336553..30655153df6ac7 100644 --- a/drivers/staging/greybus/spilib.c +++ b/drivers/staging/greybus/spilib.c @@ -245,6 +245,7 @@ static struct gb_operation *gb_spi_operation_create(struct gb_spilib *spi, /* Fill in the transfers array */ xfer = spi->first_xfer; while (msg->state != GB_SPI_STATE_OP_DONE) { + int xfer_delay; if (xfer == spi->last_xfer) xfer_len = spi->last_xfer_size; else @@ -259,7 +260,9 @@ static struct gb_operation *gb_spi_operation_create(struct gb_spilib *spi, gb_xfer->speed_hz = cpu_to_le32(xfer->speed_hz); gb_xfer->len = cpu_to_le32(xfer_len); - gb_xfer->delay_usecs = cpu_to_le16(xfer->delay_usecs); + xfer_delay = spi_delay_to_ns(&xfer->delay, xfer) / 1000; + xfer_delay = clamp_t(u16, xfer_delay, 0, U16_MAX); + gb_xfer->delay_usecs = cpu_to_le16(xfer_delay); gb_xfer->cs_change = xfer->cs_change; gb_xfer->bits_per_word = xfer->bits_per_word; From a886010c69718988756fd7873522caa0f26af398 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 8 Mar 2021 16:54:59 +0200 Subject: [PATCH 029/113] spi: spi-falcon: remove check for 'delay_usecs' The 'delay_usecs' field is being removed from the spi_transfer struct. This change removes it from the SPI Falcon driver. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20210308145502.1075689-8-aardelean@deviqon.com Signed-off-by: Mark Brown --- drivers/spi/spi-falcon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-falcon.c b/drivers/spi/spi-falcon.c index d3336a63f462dc..a7d4dffac66b25 100644 --- a/drivers/spi/spi-falcon.c +++ b/drivers/spi/spi-falcon.c @@ -377,7 +377,7 @@ static int falcon_sflash_xfer_one(struct spi_master *master, m->actual_length += t->len; - WARN_ON(t->delay_usecs || t->delay.value || t->cs_change); + WARN_ON(t->delay.value || t->cs_change); spi_flags = 0; } From 55a47532fa4c5dc3291d796dd21cc80034b5d067 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 8 Mar 2021 16:55:00 +0200 Subject: [PATCH 030/113] spi: fsl-espi: remove usage of 'delay_usecs' field The 'delay_usecs' field is being removed from the spi_transfer struct. This change removes it from the SPI FSL ESPI driver. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20210308145502.1075689-9-aardelean@deviqon.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index cf2b947c600eb5..f7066bef7b06fb 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -435,8 +435,7 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans) static int fsl_espi_do_one_msg(struct spi_master *master, struct spi_message *m) { - unsigned int delay_usecs = 0, rx_nbits = 0; - unsigned int delay_nsecs = 0, delay_nsecs1 = 0; + unsigned int rx_nbits = 0, delay_nsecs = 0; struct spi_transfer *t, trans = {}; int ret; @@ -445,16 +444,10 @@ static int fsl_espi_do_one_msg(struct spi_master *master, goto out; list_for_each_entry(t, &m->transfers, transfer_list) { - if (t->delay_usecs) { - if (t->delay_usecs > delay_usecs) { - delay_usecs = t->delay_usecs; - delay_nsecs = delay_usecs * 1000; - } - } else { - delay_nsecs1 = spi_delay_to_ns(&t->delay, t); - if (delay_nsecs1 > delay_nsecs) - delay_nsecs = delay_nsecs1; - } + unsigned int delay = spi_delay_to_ns(&t->delay, t); + + if (delay > delay_nsecs) + delay_nsecs = delay; if (t->rx_nbits > rx_nbits) rx_nbits = t->rx_nbits; } From 3ab1cce553378fc0df1b1d26d7e23d03bd4dd3b6 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 8 Mar 2021 16:55:01 +0200 Subject: [PATCH 031/113] spi: core: remove 'delay_usecs' field from spi_transfer The 'delay' field in the spi_transfer struct is meant to replace the 'delay_usecs' field. However some cleanup was required to remove the uses of 'delay_usecs'. Now that it's been cleaned up, we can remove it from the kernel tree. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20210308145502.1075689-10-aardelean@deviqon.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 1 - include/linux/spi/spi.h | 12 ------------ 2 files changed, 13 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index b08efe88ccd6c3..481427780162b7 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -3178,7 +3178,6 @@ struct spi_replaced_transfers *spi_replace_transfers( /* clear cs_change and delay for all but the last */ if (i) { xfer->cs_change = false; - xfer->delay_usecs = 0; xfer->delay.value = 0; } } diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 592897fa4f030e..ea1784a4326701 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -832,9 +832,6 @@ extern void spi_res_release(struct spi_controller *ctlr, * @delay: delay to be introduced after this transfer before * (optionally) changing the chipselect status, then starting * the next transfer or completing this @spi_message. - * @delay_usecs: microseconds to delay after this transfer before - * (optionally) changing the chipselect status, then starting - * the next transfer or completing this @spi_message. * @word_delay: inter word delay to be introduced after each word size * (set by bits_per_word) transmission. * @effective_speed_hz: the effective SCK-speed that was used to @@ -946,7 +943,6 @@ struct spi_transfer { #define SPI_NBITS_DUAL 0x02 /* 2bits transfer */ #define SPI_NBITS_QUAD 0x04 /* 4bits transfer */ u8 bits_per_word; - u16 delay_usecs; struct spi_delay delay; struct spi_delay cs_change_delay; struct spi_delay word_delay; @@ -1060,14 +1056,6 @@ spi_transfer_del(struct spi_transfer *t) static inline int spi_transfer_delay_exec(struct spi_transfer *t) { - struct spi_delay d; - - if (t->delay_usecs) { - d.value = t->delay_usecs; - d.unit = SPI_DELAY_UNIT_USECS; - return spi_delay_exec(&d, NULL); - } - return spi_delay_exec(&t->delay, t); } From 05d8a019eb057d14cdf9483318a7ee8b35a69cda Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 8 Mar 2021 16:55:02 +0200 Subject: [PATCH 032/113] spi: docs: update info about 'delay_usecs' The 'delay_usecs' field is no longer present on the spi_transfer struct. This change updates the doc to mention the usage of the (relatively) new 'delay' field. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20210308145502.1075689-11-aardelean@deviqon.com Signed-off-by: Mark Brown --- Documentation/spi/spi-summary.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/spi/spi-summary.rst b/Documentation/spi/spi-summary.rst index f1daffe10d7820..d4239025461ded 100644 --- a/Documentation/spi/spi-summary.rst +++ b/Documentation/spi/spi-summary.rst @@ -411,8 +411,11 @@ any more such messages. duplex (one pointer is NULL) transfers; + optionally defining short delays after transfers ... using - the spi_transfer.delay_usecs setting (this delay can be the - only protocol effect, if the buffer length is zero); + the spi_transfer.delay.value setting (this delay can be the + only protocol effect, if the buffer length is zero) ... + when specifying this delay the default spi_transfer.delay.unit + is microseconds, however this can be adjusted to clock cycles + or nanoseconds if needed; + whether the chipselect becomes inactive after a transfer and any delay ... by using the spi_transfer.cs_change flag; From 12ef51b116693bd77395a19ba135df68ee1673f0 Mon Sep 17 00:00:00 2001 From: Alain Volmat Date: Fri, 12 Mar 2021 11:35:29 +0100 Subject: [PATCH 033/113] spi: stm32: avoid ifdef CONFIG_PM for pm callbacks Avoid CONFIG_PM preprocessor check for pm suspend/resume callbacks and identify the functions with __maybe_unused. Signed-off-by: Alain Volmat Link: https://lore.kernel.org/r/1615545329-5496-1-git-send-email-alain.volmat@foss.st.com Signed-off-by: Mark Brown --- drivers/spi/spi-stm32.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index 25c07646101190..3cc978e477a241 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -1976,8 +1976,7 @@ static int stm32_spi_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int stm32_spi_runtime_suspend(struct device *dev) +static int __maybe_unused stm32_spi_runtime_suspend(struct device *dev) { struct spi_master *master = dev_get_drvdata(dev); struct stm32_spi *spi = spi_master_get_devdata(master); @@ -1987,7 +1986,7 @@ static int stm32_spi_runtime_suspend(struct device *dev) return pinctrl_pm_select_sleep_state(dev); } -static int stm32_spi_runtime_resume(struct device *dev) +static int __maybe_unused stm32_spi_runtime_resume(struct device *dev) { struct spi_master *master = dev_get_drvdata(dev); struct stm32_spi *spi = spi_master_get_devdata(master); @@ -1999,10 +1998,8 @@ static int stm32_spi_runtime_resume(struct device *dev) return clk_prepare_enable(spi->clk); } -#endif -#ifdef CONFIG_PM_SLEEP -static int stm32_spi_suspend(struct device *dev) +static int __maybe_unused stm32_spi_suspend(struct device *dev) { struct spi_master *master = dev_get_drvdata(dev); int ret; @@ -2014,7 +2011,7 @@ static int stm32_spi_suspend(struct device *dev) return pm_runtime_force_suspend(dev); } -static int stm32_spi_resume(struct device *dev) +static int __maybe_unused stm32_spi_resume(struct device *dev) { struct spi_master *master = dev_get_drvdata(dev); struct stm32_spi *spi = spi_master_get_devdata(master); @@ -2044,7 +2041,6 @@ static int stm32_spi_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops stm32_spi_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(stm32_spi_suspend, stm32_spi_resume) From 5ac1b909e5b60cc2735bd9174f631dc2c7f44c5a Mon Sep 17 00:00:00 2001 From: Seiya Wang Date: Tue, 16 Mar 2021 19:14:38 +0800 Subject: [PATCH 034/113] dt-bindings: spi: Add compatible for Mediatek MT8195 This commit adds dt-binding documentation of spi nor for Mediatek MT8195 SoC Platform. Signed-off-by: Seiya Wang Link: https://lore.kernel.org/r/20210316111443.3332-6-seiya.wang@mediatek.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/mediatek,spi-mtk-nor.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/spi/mediatek,spi-mtk-nor.yaml b/Documentation/devicetree/bindings/spi/mediatek,spi-mtk-nor.yaml index 55c239446a5be8..7393f30535df5b 100644 --- a/Documentation/devicetree/bindings/spi/mediatek,spi-mtk-nor.yaml +++ b/Documentation/devicetree/bindings/spi/mediatek,spi-mtk-nor.yaml @@ -31,6 +31,7 @@ properties: - mediatek,mt7623-nor - mediatek,mt7629-nor - mediatek,mt8192-nor + - mediatek,mt8195-nor - enum: - mediatek,mt8173-nor - items: From 47afc77bbfeac163d81c7a675d608c18561aa680 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 3 Mar 2021 18:28:11 +0300 Subject: [PATCH 035/113] spi: Add support for software nodes Making it possible for the drivers to assign complete software fwnodes to the devices instead of only the device properties in those nodes. Signed-off-by: Heikki Krogerus Link: https://lore.kernel.org/r/20210303152814.35070-2-heikki.krogerus@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 13 +++++++++++-- include/linux/spi/spi.h | 5 ++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index b08efe88ccd6c3..9b46998ae2a44f 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -686,6 +686,15 @@ struct spi_device *spi_new_device(struct spi_controller *ctlr, } } + if (chip->swnode) { + status = device_add_software_node(&proxy->dev, chip->swnode); + if (status) { + dev_err(&ctlr->dev, "failed to add softwade node to '%s': %d\n", + chip->modalias, status); + goto err_remove_props; + } + } + status = spi_add_device(proxy); if (status < 0) goto err_remove_props; @@ -693,8 +702,7 @@ struct spi_device *spi_new_device(struct spi_controller *ctlr, return proxy; err_remove_props: - if (chip->properties) - device_remove_properties(&proxy->dev); + device_remove_software_node(&proxy->dev); err_dev_put: spi_dev_put(proxy); return NULL; @@ -719,6 +727,7 @@ void spi_unregister_device(struct spi_device *spi) } if (ACPI_COMPANION(&spi->dev)) acpi_device_clear_enumerated(ACPI_COMPANION(&spi->dev)); + device_remove_software_node(&spi->dev); device_unregister(&spi->dev); } EXPORT_SYMBOL_GPL(spi_unregister_device); diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 592897fa4f030e..f47f94ea6fa99a 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -20,6 +20,7 @@ struct dma_chan; struct property_entry; +struct software_node; struct spi_controller; struct spi_transfer; struct spi_controller_mem_ops; @@ -1409,7 +1410,8 @@ static inline ssize_t spi_w8r16be(struct spi_device *spi, u8 cmd) * @modalias: Initializes spi_device.modalias; identifies the driver. * @platform_data: Initializes spi_device.platform_data; the particular * data stored there is driver-specific. - * @properties: Additional device properties for the device. + * @properties: Deprecated - use software node instead. + * @swnode: Software node for the device. * @controller_data: Initializes spi_device.controller_data; some * controllers need hints about hardware setup, e.g. for DMA. * @irq: Initializes spi_device.irq; depends on how the board is wired. @@ -1448,6 +1450,7 @@ struct spi_board_info { char modalias[SPI_NAME_SIZE]; const void *platform_data; const struct property_entry *properties; + const struct software_node *swnode; void *controller_data; int irq; From 2df0c4a640c55c0eff7f97907b98ad6fdfedd226 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 3 Mar 2021 18:28:12 +0300 Subject: [PATCH 036/113] ARM: pxa: icontrol: Constify the software node When device properties are supplied to the devices, in reality a software fwnode that holds those properties is created which is then assigned to the device. If the device properties are constant the software node can also be constant. Signed-off-by: Heikki Krogerus Cc: Daniel Mack Cc: Haojian Zhuang Cc: Robert Jarzmik Link: https://lore.kernel.org/r/20210303152814.35070-3-heikki.krogerus@linux.intel.com Signed-off-by: Mark Brown --- arch/arm/mach-pxa/icontrol.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-pxa/icontrol.c b/arch/arm/mach-pxa/icontrol.c index 151e26ec069683..04a12523cdee04 100644 --- a/arch/arm/mach-pxa/icontrol.c +++ b/arch/arm/mach-pxa/icontrol.c @@ -74,13 +74,17 @@ static const struct property_entry mcp251x_properties[] = { {} }; +static const struct software_node mcp251x_node = { + .properties = mcp251x_properties, +}; + static struct spi_board_info mcp251x_board_info[] = { { .modalias = "mcp2515", .max_speed_hz = 6500000, .bus_num = 3, .chip_select = 0, - .properties = mcp251x_properties, + .swnode = &mcp251x_node, .controller_data = &mcp251x_chip_info1, .irq = PXA_GPIO_TO_IRQ(ICONTROL_MCP251x_nIRQ1) }, @@ -89,7 +93,7 @@ static struct spi_board_info mcp251x_board_info[] = { .max_speed_hz = 6500000, .bus_num = 3, .chip_select = 1, - .properties = mcp251x_properties, + .swnode = &mcp251x_node, .controller_data = &mcp251x_chip_info2, .irq = PXA_GPIO_TO_IRQ(ICONTROL_MCP251x_nIRQ2) }, @@ -98,7 +102,7 @@ static struct spi_board_info mcp251x_board_info[] = { .max_speed_hz = 6500000, .bus_num = 4, .chip_select = 0, - .properties = mcp251x_properties, + .swnode = &mcp251x_node, .controller_data = &mcp251x_chip_info3, .irq = PXA_GPIO_TO_IRQ(ICONTROL_MCP251x_nIRQ3) }, @@ -107,7 +111,7 @@ static struct spi_board_info mcp251x_board_info[] = { .max_speed_hz = 6500000, .bus_num = 4, .chip_select = 1, - .properties = mcp251x_properties, + .swnode = &mcp251x_node, .controller_data = &mcp251x_chip_info4, .irq = PXA_GPIO_TO_IRQ(ICONTROL_MCP251x_nIRQ4) } From d4272a7adf26c62c5afe86b6829712de519b4a26 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 3 Mar 2021 18:28:13 +0300 Subject: [PATCH 037/113] ARM: pxa: zeus: Constify the software node When device properties are supplied to the devices, in reality a software fwnode that holds those properties is created which is then assigned to the device. If the device properties are constant the software node can also be constant. Signed-off-by: Heikki Krogerus Cc: Daniel Mack Cc: Haojian Zhuang Cc: Robert Jarzmik Link: https://lore.kernel.org/r/20210303152814.35070-4-heikki.krogerus@linux.intel.com Signed-off-by: Mark Brown --- arch/arm/mach-pxa/zeus.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c index b27fc7ac9ceab1..97700429633ee6 100644 --- a/arch/arm/mach-pxa/zeus.c +++ b/arch/arm/mach-pxa/zeus.c @@ -433,10 +433,14 @@ static const struct property_entry mcp251x_properties[] = { {} }; +static const struct software_node mcp251x_node = { + .properties = mcp251x_properties, +}; + static struct spi_board_info zeus_spi_board_info[] = { [0] = { .modalias = "mcp2515", - .properties = mcp251x_properties, + .swnode = &mcp251x_node, .irq = PXA_GPIO_TO_IRQ(ZEUS_CAN_GPIO), .max_speed_hz = 1*1000*1000, .bus_num = 3, From df41a5dad586c8ead1bb7082b4b6fcb563e02199 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 3 Mar 2021 18:28:14 +0300 Subject: [PATCH 038/113] spi: Remove support for dangling device properties >From now on only accepting complete software nodes. Signed-off-by: Heikki Krogerus Link: https://lore.kernel.org/r/20210303152814.35070-5-heikki.krogerus@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 24 +++--------------------- include/linux/spi/spi.h | 4 ---- 2 files changed, 3 insertions(+), 25 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 9b46998ae2a44f..016bbfbce90b7b 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -676,34 +676,23 @@ struct spi_device *spi_new_device(struct spi_controller *ctlr, proxy->controller_data = chip->controller_data; proxy->controller_state = NULL; - if (chip->properties) { - status = device_add_properties(&proxy->dev, chip->properties); - if (status) { - dev_err(&ctlr->dev, - "failed to add properties to '%s': %d\n", - chip->modalias, status); - goto err_dev_put; - } - } - if (chip->swnode) { status = device_add_software_node(&proxy->dev, chip->swnode); if (status) { dev_err(&ctlr->dev, "failed to add softwade node to '%s': %d\n", chip->modalias, status); - goto err_remove_props; + goto err_dev_put; } } status = spi_add_device(proxy); if (status < 0) - goto err_remove_props; + goto err_dev_put; return proxy; -err_remove_props: - device_remove_software_node(&proxy->dev); err_dev_put: + device_remove_software_node(&proxy->dev); spi_dev_put(proxy); return NULL; } @@ -764,7 +753,6 @@ static void spi_match_controller_to_boardinfo(struct spi_controller *ctlr, * * The board info passed can safely be __initdata ... but be careful of * any embedded pointers (platform_data, etc), they're copied as-is. - * Device properties are deep-copied though. * * Return: zero on success, else a negative error code. */ @@ -784,12 +772,6 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) struct spi_controller *ctlr; memcpy(&bi->board_info, info, sizeof(*info)); - if (info->properties) { - bi->board_info.properties = - property_entries_dup(info->properties); - if (IS_ERR(bi->board_info.properties)) - return PTR_ERR(bi->board_info.properties); - } mutex_lock(&board_lock); list_add_tail(&bi->list, &board_list); diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index f47f94ea6fa99a..7cb3194d5ba59a 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -19,7 +19,6 @@ #include struct dma_chan; -struct property_entry; struct software_node; struct spi_controller; struct spi_transfer; @@ -1410,7 +1409,6 @@ static inline ssize_t spi_w8r16be(struct spi_device *spi, u8 cmd) * @modalias: Initializes spi_device.modalias; identifies the driver. * @platform_data: Initializes spi_device.platform_data; the particular * data stored there is driver-specific. - * @properties: Deprecated - use software node instead. * @swnode: Software node for the device. * @controller_data: Initializes spi_device.controller_data; some * controllers need hints about hardware setup, e.g. for DMA. @@ -1444,12 +1442,10 @@ struct spi_board_info { * * platform_data goes to spi_device.dev.platform_data, * controller_data goes to spi_device.controller_data, - * device properties are copied and attached to spi_device, * irq is copied too */ char modalias[SPI_NAME_SIZE]; const void *platform_data; - const struct property_entry *properties; const struct software_node *swnode; void *controller_data; int irq; From 9d902c2a9a258e1e17cfcce7ea558b1c427b2757 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 17 Mar 2021 09:39:36 +0000 Subject: [PATCH 039/113] spi: Fix spelling mistake "softwade" -> "software" There is a spelling mistake in a dev_err message. Fix it. Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20210317093936.5572-1-colin.king@canonical.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 0706832bffdaef..2fe3c3a508664e 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -679,7 +679,7 @@ struct spi_device *spi_new_device(struct spi_controller *ctlr, if (chip->swnode) { status = device_add_software_node(&proxy->dev, chip->swnode); if (status) { - dev_err(&ctlr->dev, "failed to add softwade node to '%s': %d\n", + dev_err(&ctlr->dev, "failed to add software node to '%s': %d\n", chip->modalias, status); goto err_dev_put; } From 92bad4a4c755cdf286f6b303dd482a573f2b89e6 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 16 Mar 2021 15:09:22 -0300 Subject: [PATCH 040/113] spi: imx: Improve driver description "SPI Controller driver" is a too generic description. Make it i.MX specific instead. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20210316180922.239805-1-festevam@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 5dc4ea4b4450e5..cf5519227dbdd4 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1801,7 +1801,7 @@ static struct platform_driver spi_imx_driver = { }; module_platform_driver(spi_imx_driver); -MODULE_DESCRIPTION("SPI Controller driver"); +MODULE_DESCRIPTION("i.MX SPI Controller driver"); MODULE_AUTHOR("Sascha Hauer, Pengutronix"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DRIVER_NAME); From 79c6246ae8793448c05da86a4c82298eed8549b0 Mon Sep 17 00:00:00 2001 From: Alain Volmat Date: Thu, 18 Mar 2021 08:24:50 +0100 Subject: [PATCH 041/113] spi: stm32: Fix use-after-free on unbind stm32_spi_remove() accesses the driver's private data after calling spi_unregister_master() even though that function releases the last reference on the spi_master and thereby frees the private data. Fix by switching over to the new devm_spi_alloc_master() helper which keeps the private data accessible until the driver has unbound. Fixes: 8d559a64f00b ("spi: stm32: drop devres version of spi_register_master") Reported-by: Lukas Wunner Signed-off-by: Alain Volmat Link: https://lore.kernel.org/r/1616052290-10887-1-git-send-email-alain.volmat@foss.st.com Signed-off-by: Mark Brown --- drivers/spi/spi-stm32.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index 3cc978e477a241..aa2c5018ed539b 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -1803,7 +1803,7 @@ static int stm32_spi_probe(struct platform_device *pdev) struct reset_control *rst; int ret; - master = spi_alloc_master(&pdev->dev, sizeof(struct stm32_spi)); + master = devm_spi_alloc_master(&pdev->dev, sizeof(struct stm32_spi)); if (!master) { dev_err(&pdev->dev, "spi master allocation failed\n"); return -ENOMEM; @@ -1821,18 +1821,16 @@ static int stm32_spi_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); spi->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(spi->base)) { - ret = PTR_ERR(spi->base); - goto err_master_put; - } + if (IS_ERR(spi->base)) + return PTR_ERR(spi->base); spi->phys_addr = (dma_addr_t)res->start; spi->irq = platform_get_irq(pdev, 0); - if (spi->irq <= 0) { - ret = dev_err_probe(&pdev->dev, spi->irq, "failed to get irq\n"); - goto err_master_put; - } + if (spi->irq <= 0) + return dev_err_probe(&pdev->dev, spi->irq, + "failed to get irq\n"); + ret = devm_request_threaded_irq(&pdev->dev, spi->irq, spi->cfg->irq_handler_event, spi->cfg->irq_handler_thread, @@ -1840,20 +1838,20 @@ static int stm32_spi_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "irq%d request failed: %d\n", spi->irq, ret); - goto err_master_put; + 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); - goto err_master_put; + return ret; } ret = clk_prepare_enable(spi->clk); if (ret) { dev_err(&pdev->dev, "clk enable failed: %d\n", ret); - goto err_master_put; + return ret; } spi->clk_rate = clk_get_rate(spi->clk); if (!spi->clk_rate) { @@ -1949,8 +1947,6 @@ static int stm32_spi_probe(struct platform_device *pdev) dma_release_channel(spi->dma_rx); err_clk_disable: clk_disable_unprepare(spi->clk); -err_master_put: - spi_master_put(master); return ret; } From 08b020d3e9a87fb6d94b02782c42c001a4e084f4 Mon Sep 17 00:00:00 2001 From: Leilk Liu Date: Mon, 22 Mar 2021 13:52:41 +0800 Subject: [PATCH 042/113] spi: update spi master bindings for MT8195 SoC Add a DT binding documentation for the MT8195 soc. Signed-off-by: leilk.liu Link: https://lore.kernel.org/r/20210322055244.30179-2-leilk.liu@mediatek.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/spi-mt65xx.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/spi/spi-mt65xx.txt b/Documentation/devicetree/bindings/spi/spi-mt65xx.txt index 7bae7eef26c7ff..4d0e4c15c4ea79 100644 --- a/Documentation/devicetree/bindings/spi/spi-mt65xx.txt +++ b/Documentation/devicetree/bindings/spi/spi-mt65xx.txt @@ -12,6 +12,7 @@ Required properties: - mediatek,mt8173-spi: for mt8173 platforms - mediatek,mt8183-spi: for mt8183 platforms - "mediatek,mt8192-spi", "mediatek,mt6765-spi": for mt8192 platforms + - "mediatek,mt8195-spi", "mediatek,mt6765-spi": for mt8195 platforms - "mediatek,mt8516-spi", "mediatek,mt2712-spi": for mt8516 platforms - "mediatek,mt6779-spi", "mediatek,mt6765-spi": for mt6779 platforms From f42698a8dc589dc7cc8e36641e86e6a9b3b32f9b Mon Sep 17 00:00:00 2001 From: Leilk Liu Date: Mon, 22 Mar 2021 13:52:42 +0800 Subject: [PATCH 043/113] spi: update spi slave bindings for MT8195 SoC Add a DT binding documentation for the MT8195 soc. Signed-off-by: Leilk Liu Link: https://lore.kernel.org/r/20210322055244.30179-3-leilk.liu@mediatek.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/spi-slave-mt27xx.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/spi/spi-slave-mt27xx.txt b/Documentation/devicetree/bindings/spi/spi-slave-mt27xx.txt index c37e5a179b21ec..9192724540fd9a 100644 --- a/Documentation/devicetree/bindings/spi/spi-slave-mt27xx.txt +++ b/Documentation/devicetree/bindings/spi/spi-slave-mt27xx.txt @@ -3,6 +3,7 @@ Binding for MTK SPI Slave controller Required properties: - compatible: should be one of the following. - mediatek,mt2712-spi-slave: for mt2712 platforms + - mediatek,mt8195-spi-slave: for mt8195 platforms - reg: Address and length of the register set for the device. - interrupts: Should contain spi interrupt. - clocks: phandles to input clocks. From d666a833b0b9f5b8e08ecdc002a4cf5d34932b7a Mon Sep 17 00:00:00 2001 From: Leilk Liu Date: Mon, 22 Mar 2021 13:52:43 +0800 Subject: [PATCH 044/113] spi: mediatek: add mtk_spi_compatible support this patch adds max_fifo_size and must_rx compat support. Signed-off-by: Leilk Liu Link: https://lore.kernel.org/r/20210322055244.30179-4-leilk.liu@mediatek.com Signed-off-by: Mark Brown --- drivers/spi/spi-slave-mt27xx.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-slave-mt27xx.c b/drivers/spi/spi-slave-mt27xx.c index 44edaa360405a6..7e6fadc88cef03 100644 --- a/drivers/spi/spi-slave-mt27xx.c +++ b/drivers/spi/spi-slave-mt27xx.c @@ -10,6 +10,8 @@ #include #include #include +#include + #define SPIS_IRQ_EN_REG 0x0 #define SPIS_IRQ_CLR_REG 0x4 @@ -61,8 +63,6 @@ #define SPIS_DMA_ADDR_EN BIT(1) #define SPIS_SOFT_RST BIT(0) -#define MTK_SPI_SLAVE_MAX_FIFO_SIZE 512U - struct mtk_spi_slave { struct device *dev; void __iomem *base; @@ -70,10 +70,19 @@ struct mtk_spi_slave { struct completion xfer_done; struct spi_transfer *cur_transfer; bool slave_aborted; + const struct mtk_spi_compatible *dev_comp; }; +struct mtk_spi_compatible { + const u32 max_fifo_size; + bool must_rx; +}; +static const struct mtk_spi_compatible mt2712_compat = { + .max_fifo_size = 512, +}; static const struct of_device_id mtk_spi_slave_of_match[] = { - { .compatible = "mediatek,mt2712-spi-slave", }, + { .compatible = "mediatek,mt2712-spi-slave", + .data = (void *)&mt2712_compat,}, {} }; MODULE_DEVICE_TABLE(of, mtk_spi_slave_of_match); @@ -272,7 +281,7 @@ static int mtk_spi_slave_transfer_one(struct spi_controller *ctlr, mdata->slave_aborted = false; mdata->cur_transfer = xfer; - if (xfer->len > MTK_SPI_SLAVE_MAX_FIFO_SIZE) + if (xfer->len > mdata->dev_comp->max_fifo_size) return mtk_spi_slave_dma_transfer(ctlr, spi, xfer); else return mtk_spi_slave_fifo_transfer(ctlr, spi, xfer); @@ -369,6 +378,7 @@ static int mtk_spi_slave_probe(struct platform_device *pdev) struct spi_controller *ctlr; struct mtk_spi_slave *mdata; int irq, ret; + const struct of_device_id *of_id; ctlr = spi_alloc_slave(&pdev->dev, sizeof(*mdata)); if (!ctlr) { @@ -386,7 +396,17 @@ static int mtk_spi_slave_probe(struct platform_device *pdev) ctlr->setup = mtk_spi_slave_setup; ctlr->slave_abort = mtk_slave_abort; + of_id = of_match_node(mtk_spi_slave_of_match, pdev->dev.of_node); + if (!of_id) { + dev_err(&pdev->dev, "failed to probe of_node\n"); + ret = -EINVAL; + goto err_put_ctlr; + } mdata = spi_controller_get_devdata(ctlr); + mdata->dev_comp = of_id->data; + + if (mdata->dev_comp->must_rx) + ctlr->flags = SPI_MASTER_MUST_RX; platform_set_drvdata(pdev, ctlr); From 1527b09bc80018f02fe0b6d14e97c95f93596221 Mon Sep 17 00:00:00 2001 From: Leilk Liu Date: Mon, 22 Mar 2021 13:52:44 +0800 Subject: [PATCH 045/113] spi: mediatek: add mt8195 spi slave support this patch adds mt8195 spi slave compatible support. Signed-off-by: Leilk Liu Link: https://lore.kernel.org/r/20210322055244.30179-5-leilk.liu@mediatek.com Signed-off-by: Mark Brown --- drivers/spi/spi-slave-mt27xx.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/spi/spi-slave-mt27xx.c b/drivers/spi/spi-slave-mt27xx.c index 7e6fadc88cef03..f199a6c4738a0b 100644 --- a/drivers/spi/spi-slave-mt27xx.c +++ b/drivers/spi/spi-slave-mt27xx.c @@ -77,12 +77,20 @@ struct mtk_spi_compatible { const u32 max_fifo_size; bool must_rx; }; + static const struct mtk_spi_compatible mt2712_compat = { .max_fifo_size = 512, }; +static const struct mtk_spi_compatible mt8195_compat = { + .max_fifo_size = 128, + .must_rx = true, +}; + static const struct of_device_id mtk_spi_slave_of_match[] = { { .compatible = "mediatek,mt2712-spi-slave", .data = (void *)&mt2712_compat,}, + { .compatible = "mediatek,mt8195-spi-slave", + .data = (void *)&mt8195_compat,}, {} }; MODULE_DEVICE_TABLE(of, mtk_spi_slave_of_match); From c9831087356b7ae02dfb22b3121117c48aa9e95b Mon Sep 17 00:00:00 2001 From: Jay Fang Date: Wed, 24 Mar 2021 14:16:32 +0800 Subject: [PATCH 046/113] spi: spi-topcliff-pch: Fix checkpatch spacing error Fix checkpatch error: ERROR: space prohibited before that '++' (ctx:WxB) #1204: FILE: spi-topcliff-pch.c:1204: + for (i = 0; i < cnt; i ++) { ^ Signed-off-by: Jay Fang Link: https://lore.kernel.org/r/1616566602-13894-2-git-send-email-f.fangjian@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-topcliff-pch.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index b459e369079f81..b8870784fc6eff 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1201,7 +1201,8 @@ static void pch_spi_process_messages(struct work_struct *pwork) if (data->use_dma) { int i; char *save_rx_buf = data->cur_trans->rx_buf; - for (i = 0; i < cnt; i ++) { + + for (i = 0; i < cnt; i++) { pch_spi_handle_dma(data, &bpw); if (!pch_spi_start_transfer(data)) { data->transfer_complete = true; From e13a870ffaa60f459892eb4600a286b4db7da5ad Mon Sep 17 00:00:00 2001 From: Jay Fang Date: Wed, 24 Mar 2021 14:16:33 +0800 Subject: [PATCH 047/113] spi: sprd: Fix checkpatch spacing error Fix checkpatch error: ERROR: space prohibited before that close parenthesis ')' #213: FILE: spi-sprd-adi.c:213: + rd_addr = (val & RD_ADDR_MASK ) >> RD_ADDR_SHIFT; Signed-off-by: Jay Fang Link: https://lore.kernel.org/r/1616566602-13894-3-git-send-email-f.fangjian@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-sprd-adi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-sprd-adi.c b/drivers/spi/spi-sprd-adi.c index 392ec5cfa3d61e..ab19068be86755 100644 --- a/drivers/spi/spi-sprd-adi.c +++ b/drivers/spi/spi-sprd-adi.c @@ -210,7 +210,7 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val) * address. Then we can check the returned register address to validate * data. */ - rd_addr = (val & RD_ADDR_MASK ) >> RD_ADDR_SHIFT; + rd_addr = (val & RD_ADDR_MASK) >> RD_ADDR_SHIFT; if (rd_addr != (reg_paddr & REG_ADDR_LOW_MASK)) { dev_err(sadi->dev, "read error, reg addr = 0x%x, val = 0x%x\n", From c07caca3cea90332e410ba3e53bc264ae1f2c9c9 Mon Sep 17 00:00:00 2001 From: Jay Fang Date: Wed, 24 Mar 2021 14:16:34 +0800 Subject: [PATCH 048/113] spi: pxa2xx: Fix checkpatch spacing errors Fix checkpatch errors: ERROR: space prohibited before that ',' (ctx:WxW) #255: FILE: spi-pxa2xx-pci.c:255: + ssp->clk = clk_register_fixed_rate(&dev->dev, buf , NULL, 0, ^ ERROR: "foo* bar" should be "foo *bar" #621: FILE: spi-pxa2xx.c:621: +static void int_error_stop(struct driver_data *drv_data, const char* msg) Signed-off-by: Jay Fang Link: https://lore.kernel.org/r/1616566602-13894-4-git-send-email-f.fangjian@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx-pci.c | 2 +- drivers/spi/spi-pxa2xx.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c index 14fc41ed2361df..1833f5876e9fa1 100644 --- a/drivers/spi/spi-pxa2xx-pci.c +++ b/drivers/spi/spi-pxa2xx-pci.c @@ -252,7 +252,7 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, ssp->irq = pci_irq_vector(dev, 0); snprintf(buf, sizeof(buf), "pxa2xx-spi.%d", ssp->port_id); - ssp->clk = clk_register_fixed_rate(&dev->dev, buf , NULL, 0, + ssp->clk = clk_register_fixed_rate(&dev->dev, buf, NULL, 0, c->max_clk_rate); if (IS_ERR(ssp->clk)) return PTR_ERR(ssp->clk); diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 0cc767283674b2..b83f325fe51b2b 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -618,7 +618,7 @@ static void reset_sccr1(struct driver_data *drv_data) pxa2xx_spi_write(drv_data, SSCR1, sccr1_reg); } -static void int_error_stop(struct driver_data *drv_data, const char* msg) +static void int_error_stop(struct driver_data *drv_data, const char *msg) { /* Stop and reset SSP */ write_SSSR_CS(drv_data, drv_data->clear_sr); From f2edb98e806d0bf7947e5da352d69f4fbb063b04 Mon Sep 17 00:00:00 2001 From: Jay Fang Date: Wed, 24 Mar 2021 14:16:35 +0800 Subject: [PATCH 049/113] spi: omap-100k: Fix checkpatch spacing errors Fix checkpatch errors: ERROR: space prohibited before that ',' (ctx:WxW) #113: FILE: spi-omap-100k.c:113: + writew(data , spi100k->base + SPI_TX_MSB); ^ ERROR: space prohibited before that ',' (ctx:WxW) #249: FILE: spi-omap-100k.c:249: + writew(0x3e , spi100k->base + SPI_SETUP1); ^ ERROR: space prohibited before that ',' (ctx:WxW) #250: FILE: spi-omap-100k.c:250: + writew(0x00 , spi100k->base + SPI_STATUS); ^ ERROR: space prohibited before that ',' (ctx:WxW) #251: FILE: spi-omap-100k.c:251: + writew(0x3e , spi100k->base + SPI_CTRL); ^ Signed-off-by: Jay Fang Link: https://lore.kernel.org/r/1616566602-13894-5-git-send-email-f.fangjian@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-omap-100k.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index 36a4922a134a13..189fd2dda37bf9 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c @@ -110,7 +110,7 @@ static void spi100k_write_data(struct spi_master *master, int len, int data) } spi100k_enable_clock(master); - writew(data , spi100k->base + SPI_TX_MSB); + writew(data, spi100k->base + SPI_TX_MSB); writew(SPI_CTRL_SEN(0) | SPI_CTRL_WORD_SIZE(len) | @@ -246,9 +246,9 @@ static int omap1_spi100k_setup_transfer(struct spi_device *spi, cs->word_len = word_len; /* SPI init before transfer */ - writew(0x3e , spi100k->base + SPI_SETUP1); - writew(0x00 , spi100k->base + SPI_STATUS); - writew(0x3e , spi100k->base + SPI_CTRL); + writew(0x3e, spi100k->base + SPI_SETUP1); + writew(0x00, spi100k->base + SPI_STATUS); + writew(0x3e, spi100k->base + SPI_CTRL); return 0; } From 99b3a36204564cb689cd862794043e1b8f5863b1 Mon Sep 17 00:00:00 2001 From: Jay Fang Date: Wed, 24 Mar 2021 14:16:36 +0800 Subject: [PATCH 050/113] spi: spi-mtk-nor: Fix checkpatch spacing error Fix checkpatch error: ERROR: space required before the open parenthesis '(' #295: FILE: spi-mtk-nor.c:295: + switch(op->data.dir) { Signed-off-by: Jay Fang Link: https://lore.kernel.org/r/1616566602-13894-6-git-send-email-f.fangjian@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-mtk-nor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c index 2e2f36a2e38501..41e7b341d2616f 100644 --- a/drivers/spi/spi-mtk-nor.c +++ b/drivers/spi/spi-mtk-nor.c @@ -292,7 +292,7 @@ static bool mtk_nor_supports_op(struct spi_mem *mem, return false; if ((op->addr.nbytes == 3) || (op->addr.nbytes == 4)) { - switch(op->data.dir) { + switch (op->data.dir) { case SPI_MEM_DATA_IN: if (mtk_nor_match_read(op)) return true; From 211f8a0a39cd7dcd9c14744053ea681a0e7eb36d Mon Sep 17 00:00:00 2001 From: Jay Fang Date: Wed, 24 Mar 2021 14:16:37 +0800 Subject: [PATCH 051/113] spi: dln2: Fix open brace following function definitions go on the next line Fix checkpatch error: ERROR: open brace '{' following function definitions go on the next line #545: FILE: spi-dln2.c:545: +static int dln2_spi_rdwr(struct dln2_spi *dln2, const u8 *tx_data, + u8 *rx_data, u16 data_len, u8 attr) { Signed-off-by: Jay Fang Link: https://lore.kernel.org/r/1616566602-13894-7-git-send-email-f.fangjian@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-dln2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-dln2.c b/drivers/spi/spi-dln2.c index 75b33d7d14b046..3902eadb892f91 100644 --- a/drivers/spi/spi-dln2.c +++ b/drivers/spi/spi-dln2.c @@ -543,7 +543,8 @@ static int dln2_spi_read_write_one(struct dln2_spi *dln2, const u8 *tx_data, * single ones due to device buffer constraints. */ static int dln2_spi_rdwr(struct dln2_spi *dln2, const u8 *tx_data, - u8 *rx_data, u16 data_len, u8 attr) { + u8 *rx_data, u16 data_len, u8 attr) +{ int ret; u16 len; u8 temp_attr; From f96c19fab393db16a2db78183ca8f584ee1b716a Mon Sep 17 00:00:00 2001 From: Jay Fang Date: Wed, 24 Mar 2021 14:16:38 +0800 Subject: [PATCH 052/113] spi: spi-bitbang: Fix open brace following function definitions go on the next line Fix checkpatch errors: ERROR: open brace '{' following function definitions go on the next line #54: FILE: spi-bitbang.c:54: ERROR: open brace '{' following function definitions go on the next line #82: FILE: spi-bitbang.c:82: ERROR: open brace '{' following function definitions go on the next line #110: FILE: spi-bitbang.c:110: Signed-off-by: Jay Fang Link: https://lore.kernel.org/r/1616566602-13894-8-git-send-email-f.fangjian@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-bitbang.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index 1a7352abd87860..6a6af85aebfd80 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -60,7 +60,8 @@ static unsigned bitbang_txrx_8( unsigned ns, struct spi_transfer *t, unsigned flags -) { +) +{ unsigned bits = t->bits_per_word; unsigned count = t->len; const u8 *tx = t->tx_buf; @@ -88,7 +89,8 @@ static unsigned bitbang_txrx_16( unsigned ns, struct spi_transfer *t, unsigned flags -) { +) +{ unsigned bits = t->bits_per_word; unsigned count = t->len; const u16 *tx = t->tx_buf; @@ -116,7 +118,8 @@ static unsigned bitbang_txrx_32( unsigned ns, struct spi_transfer *t, unsigned flags -) { +) +{ unsigned bits = t->bits_per_word; unsigned count = t->len; const u32 *tx = t->tx_buf; From 45793de7bf89fbd0fd1e2db9dda4e58a9c1395ee Mon Sep 17 00:00:00 2001 From: Jay Fang Date: Wed, 24 Mar 2021 14:16:39 +0800 Subject: [PATCH 053/113] spi: jcore: Fix trailing statements should be on next line Fix checkpatch error: ERROR: trailing statements should be on next line #85: FILE: spi-jcore.c:85: + if (speed == hw->speed_hz) return; Signed-off-by: Jay Fang Link: https://lore.kernel.org/r/1616566602-13894-9-git-send-email-f.fangjian@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-jcore.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-jcore.c b/drivers/spi/spi-jcore.c index bba10f030e33da..74c8319c29f170 100644 --- a/drivers/spi/spi-jcore.c +++ b/drivers/spi/spi-jcore.c @@ -82,7 +82,8 @@ static void jcore_spi_chipsel(struct spi_device *spi, bool value) static void jcore_spi_baudrate(struct jcore_spi *hw, int speed) { - if (speed == hw->speed_hz) return; + if (speed == hw->speed_hz) + return; hw->speed_hz = speed; if (speed >= hw->clock_freq / 2) hw->speed_reg = 0; From 6ca6ad908e965b1b01c31618971a1de7b6307a21 Mon Sep 17 00:00:00 2001 From: Jay Fang Date: Wed, 24 Mar 2021 14:16:40 +0800 Subject: [PATCH 054/113] spi: spi-mem: Fix code indent should use tabs where possible Fix checkpatch errors: ERROR: code indent should use tabs where possible #624: FILE: spi-mem.c:624: ERROR: code indent should use tabs where possible #626: FILE: spi-mem.c:626: ERROR: code indent should use tabs where possible #627: FILE: spi-mem.c:627: Signed-off-by: Jay Fang Link: https://lore.kernel.org/r/1616566602-13894-10-git-send-email-f.fangjian@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-mem.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index dc713b0c3c4d84..1513553e40805a 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -621,10 +621,10 @@ EXPORT_SYMBOL_GPL(devm_spi_mem_dirmap_create); static int devm_spi_mem_dirmap_match(struct device *dev, void *res, void *data) { - struct spi_mem_dirmap_desc **ptr = res; + struct spi_mem_dirmap_desc **ptr = res; - if (WARN_ON(!ptr || !*ptr)) - return 0; + if (WARN_ON(!ptr || !*ptr)) + return 0; return *ptr == data; } From 02621799966babf50d1d1dc523e834366904b55d Mon Sep 17 00:00:00 2001 From: Jay Fang Date: Wed, 24 Mar 2021 14:16:41 +0800 Subject: [PATCH 055/113] spi: rockchip: Fix code indent should use tabs where possible Fix checkpatch errors: ERROR: code indent should use tabs where possible #484: FILE: spi-rockchip.c:484: +^I | CR0_BHT_8BIT << CR0_BHT_OFFSET$ ERROR: code indent should use tabs where possible #485: FILE: spi-rockchip.c:485: +^I | CR0_SSD_ONE << CR0_SSD_OFFSET$ ERROR: code indent should use tabs where possible #486: FILE: spi-rockchip.c:486: +^I | CR0_EM_BIG << CR0_EM_OFFSET;$ Signed-off-by: Jay Fang Link: https://lore.kernel.org/r/1616566602-13894-11-git-send-email-f.fangjian@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-rockchip.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index 0d75080da6480e..52d6259d96edad 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -481,9 +481,9 @@ static int rockchip_spi_config(struct rockchip_spi *rs, bool use_dma, bool slave_mode) { u32 cr0 = CR0_FRF_SPI << CR0_FRF_OFFSET - | CR0_BHT_8BIT << CR0_BHT_OFFSET - | CR0_SSD_ONE << CR0_SSD_OFFSET - | CR0_EM_BIG << CR0_EM_OFFSET; + | CR0_BHT_8BIT << CR0_BHT_OFFSET + | CR0_SSD_ONE << CR0_SSD_OFFSET + | CR0_EM_BIG << CR0_EM_OFFSET; u32 cr1; u32 dmacr = 0; From 9d5376872162dc70c16ae8379dba0266f35883f9 Mon Sep 17 00:00:00 2001 From: Jay Fang Date: Wed, 24 Mar 2021 14:16:42 +0800 Subject: [PATCH 056/113] spi: pl022: Fix trailing whitespace Fix checkpatch error: ERROR: trailing whitespace #1198: FILE: spi-pl022.c:1198: Signed-off-by: Jay Fang Link: https://lore.kernel.org/r/1616566602-13894-12-git-send-email-f.fangjian@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-pl022.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index fd74ddfbb68697..d7ed1885e92cd1 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -1195,7 +1195,7 @@ static int pl022_dma_autoprobe(struct pl022 *pl022) err_no_rxchan: return err; } - + static void terminate_dma(struct pl022 *pl022) { struct dma_chan *rxchan = pl022->dma_rx_channel; From 0467a97367d4767d284ad46ba0e6413b621256a0 Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Tue, 16 Mar 2021 08:59:27 +0100 Subject: [PATCH 057/113] spi: fspi: enable fspi driver for on imx8mp add compatible entry in nxp_fspi driver for imx8mp. Signed-off-by: Heiko Schocher Link: https://lore.kernel.org/r/20210316075928.1763460-2-hs@denx.de Signed-off-by: Mark Brown --- drivers/spi/spi-nxp-fspi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index ed1e888c7ece41..6e6c2403944dd2 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -1242,6 +1242,7 @@ static int nxp_fspi_resume(struct device *dev) static const struct of_device_id nxp_fspi_dt_ids[] = { { .compatible = "nxp,lx2160a-fspi", .data = (void *)&lx2160a_data, }, { .compatible = "nxp,imx8mm-fspi", .data = (void *)&imx8mm_data, }, + { .compatible = "nxp,imx8mp-fspi", .data = (void *)&imx8mm_data, }, { .compatible = "nxp,imx8qxp-fspi", .data = (void *)&imx8qxp_data, }, { .compatible = "nxp,imx8dxl-fspi", .data = (void *)&imx8dxl_data, }, { /* sentinel */ } From 2801a62dfad46ff228d00126ce8592594c1d0613 Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Tue, 16 Mar 2021 08:59:28 +0100 Subject: [PATCH 058/113] dt-bindings: spi: add compatible entry for imx8mp in FlexSPI controller add compatible entry "nxp,imx8mp-fspi" in NXP FlexSPI controller Signed-off-by: Heiko Schocher Link: https://lore.kernel.org/r/20210316075928.1763460-3-hs@denx.de Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/spi-nxp-fspi.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/spi/spi-nxp-fspi.txt b/Documentation/devicetree/bindings/spi/spi-nxp-fspi.txt index df178d1b62e67a..8f34a7c7d8b843 100644 --- a/Documentation/devicetree/bindings/spi/spi-nxp-fspi.txt +++ b/Documentation/devicetree/bindings/spi/spi-nxp-fspi.txt @@ -4,6 +4,7 @@ Required properties: - compatible : Should be "nxp,lx2160a-fspi" "nxp,imx8qxp-fspi" "nxp,imx8mm-fspi" + "nxp,imx8mp-fspi" "nxp,imx8dxl-fspi" - reg : First contains the register location and length, From 3ed4c84cc7ac59dd383f1d77f7b04148ede2548d Mon Sep 17 00:00:00 2001 From: Eddie James Date: Wed, 24 Mar 2021 17:05:16 -0500 Subject: [PATCH 059/113] spi: fsi: Remove multiple sequenced ops for restricted chips Updated restricted chips have trouble processing multiple sequenced operations. So remove the capability to sequence multiple operations and reduce the maximum transfer size to 8 bytes. Signed-off-by: Eddie James Reviewed-by: Joel Stanley Link: https://lore.kernel.org/r/20210324220516.41192-1-eajames@linux.ibm.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsi.c | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c index 3920cd3286d8a7..de359718e816f6 100644 --- a/drivers/spi/spi-fsi.c +++ b/drivers/spi/spi-fsi.c @@ -26,7 +26,7 @@ #define SPI_FSI_BASE 0x70000 #define SPI_FSI_INIT_TIMEOUT_MS 1000 #define SPI_FSI_MAX_XFR_SIZE 2048 -#define SPI_FSI_MAX_XFR_SIZE_RESTRICTED 32 +#define SPI_FSI_MAX_XFR_SIZE_RESTRICTED 8 #define SPI_FSI_ERROR 0x0 #define SPI_FSI_COUNTER_CFG 0x1 @@ -265,14 +265,12 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx, struct fsi_spi_sequence *seq, struct spi_transfer *transfer) { - bool docfg = false; int loops; int idx; int rc; u8 val = 0; u8 len = min(transfer->len, 8U); u8 rem = transfer->len % len; - u64 cfg = 0ULL; loops = transfer->len / len; @@ -292,28 +290,17 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx, return -EINVAL; } - if (ctx->restricted) { - const int eidx = rem ? 5 : 6; - - while (loops > 1 && idx <= eidx) { - idx = fsi_spi_sequence_add(seq, val); - loops--; - docfg = true; - } - - if (loops > 1) { - dev_warn(ctx->dev, "No sequencer slots; aborting.\n"); - return -EINVAL; - } + if (ctx->restricted && loops > 1) { + dev_warn(ctx->dev, + "Transfer too large; no branches permitted.\n"); + return -EINVAL; } if (loops > 1) { + u64 cfg = SPI_FSI_COUNTER_CFG_LOOPS(loops - 1); + fsi_spi_sequence_add(seq, SPI_FSI_SEQUENCE_BRANCH(idx)); - docfg = true; - } - if (docfg) { - cfg = SPI_FSI_COUNTER_CFG_LOOPS(loops - 1); if (transfer->rx_buf) cfg |= SPI_FSI_COUNTER_CFG_N2_RX | SPI_FSI_COUNTER_CFG_N2_TX | From 413c601e8fd0e4adab67e0775dd84e63be6d803e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 28 Mar 2021 14:15:30 +0200 Subject: [PATCH 060/113] spi: pl022: User more sensible defaults When using the device tree, which must be considered normal these days, in order to get some kind of normal functionality out of the PL022 users have to actively go into the device tree and edit the SPI clients like this: spi { compatible = "arm,pl022"; num-cs = <1>; cs-gpios = <&gpio 0 GPIO_ACTIVE_LOW>; foo@0 { compatible = "foo"; reg = <0>; pl022,interface = <0>; pl022,com-mode = <0>; }; }; Otherwise the PL022 will come up as a client (slave) and using polling mode. This is quite unintuitive and many users will get their device trees wrong. Alter the defaults such that we come up in host mode (master) and use interrupt mode. Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20210328121530.1983081-1-linus.walleij@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-pl022.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index d7ed1885e92cd1..559d179fa5e723 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -1820,9 +1820,9 @@ static int calculate_effective_freq(struct pl022 *pl022, int freq, struct * supplies it. */ static const struct pl022_config_chip pl022_default_chip_info = { - .com_mode = POLLING_TRANSFER, + .com_mode = INTERRUPT_TRANSFER, .iface = SSP_INTERFACE_MOTOROLA_SPI, - .hierarchy = SSP_SLAVE, + .hierarchy = SSP_MASTER, .slave_tx_disable = DO_NOT_DRIVE_TX, .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM, .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC, From 4179e576b56d82e5ce007b9f548efb90605e2713 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 30 Mar 2021 18:49:05 +0200 Subject: [PATCH 061/113] spi: pl022: Drop custom per-chip cs_control Drop the custom cs_control() assigned through platform data, we have no in-tree users and the only out-of-tree use I have ever seen of this facility is to pull GPIO lines, which is something the driver can already do for us. Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20210330164907.2346010-1-linus.walleij@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-pl022.c | 26 ++------------------------ include/linux/amba/pl022.h | 3 --- 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 559d179fa5e723..8a475fdbeded92 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -412,7 +412,6 @@ struct pl022 { * @enable_dma: Whether to enable DMA or not * @read: function ptr to be used to read when doing xfer for this chip * @write: function ptr to be used to write when doing xfer for this chip - * @cs_control: chip select callback provided by chip * @xfer_type: polling/interrupt/DMA * * Runtime state of the SSP controller, maintained per chip, @@ -427,22 +426,9 @@ struct chip_data { bool enable_dma; enum ssp_reading read; enum ssp_writing write; - void (*cs_control) (u32 command); int xfer_type; }; -/** - * null_cs_control - Dummy chip select function - * @command: select/delect the chip - * - * If no chip select function is provided by client this is used as dummy - * chip select - */ -static void null_cs_control(u32 command) -{ - pr_debug("pl022: dummy chip select control, CS=0x%x\n", command); -} - /** * internal_cs_control - Control chip select signals via SSP_CSR. * @pl022: SSP driver private data structure @@ -470,8 +456,6 @@ static void pl022_cs_control(struct pl022 *pl022, u32 command) internal_cs_control(pl022, command); else if (gpio_is_valid(pl022->cur_cs)) gpio_set_value(pl022->cur_cs, command); - else - pl022->cur_chip->cs_control(command); } /** @@ -1829,7 +1813,6 @@ static const struct pl022_config_chip pl022_default_chip_info = { .ctrl_len = SSP_BITS_8, .wait_state = SSP_MWIRE_WAIT_ZERO, .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, - .cs_control = null_cs_control, }; /** @@ -1940,13 +1923,8 @@ static int pl022_setup(struct spi_device *spi) /* Now set controller state based on controller data */ chip->xfer_type = chip_info->com_mode; - if (!chip_info->cs_control) { - chip->cs_control = null_cs_control; - if (!gpio_is_valid(pl022->chipselects[spi->chip_select])) - dev_warn(&spi->dev, - "invalid chip select\n"); - } else - chip->cs_control = chip_info->cs_control; + if (!gpio_is_valid(pl022->chipselects[spi->chip_select])) + dev_warn(&spi->dev, "invalid chip select\n"); /* Check bits per word with vendor specific range */ if ((bits <= 3) || (bits > pl022->vendor->max_bpw)) { diff --git a/include/linux/amba/pl022.h b/include/linux/amba/pl022.h index 131b27c9720931..29274cedefdeda 100644 --- a/include/linux/amba/pl022.h +++ b/include/linux/amba/pl022.h @@ -265,8 +265,6 @@ struct pl022_ssp_controller { * @duplex: Microwire interface: Full/Half duplex * @clkdelay: on the PL023 variant, the delay in feeback clock cycles * before sampling the incoming line - * @cs_control: function pointer to board-specific function to - * assert/deassert I/O port to control HW generation of devices chip-select. */ struct pl022_config_chip { enum ssp_interface iface; @@ -280,7 +278,6 @@ struct pl022_config_chip { enum ssp_microwire_wait_state wait_state; enum ssp_duplex duplex; enum ssp_clkdelay clkdelay; - void (*cs_control) (u32 control); }; #endif /* _SSP_PL022_H */ From 77f983a9df421fa00ca6a2f494dc79f8afca75a2 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 30 Mar 2021 18:49:06 +0200 Subject: [PATCH 062/113] spi: pl022: Use GPIOs looked up by the core The SPI core looks up GPIO lines from the device tree, so let's stop trying to do that on our own and rely on the core to do this for us. In addition to the GPIO line we also need to keep track of the chip select index separately, as the native chip select needs this index. The driver was reusing the same GPIO array for native chip select indices, so keep this in a separate state variable instead. The facility to pass in custom GPIO lines from the platform data can go, because even if we do have out-of-tree code that want to use platform data, they can soon pass in GPIOs using machine GPIO descriptor tables which will be available after the next step when we convert the driver to using GPIO descriptors. The implicit inclusion of is made explicit as we no longer need to include . Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20210330164907.2346010-2-linus.walleij@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-pl022.c | 70 ++++++-------------------------------- include/linux/amba/pl022.h | 7 ---- 2 files changed, 10 insertions(+), 67 deletions(-) diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 8a475fdbeded92..680f9cdfe2955c 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include /* @@ -362,8 +362,8 @@ struct vendor_data { * @sgt_tx: scattertable for the TX transfer * @dummypage: a dummy page used for driving data on the bus with DMA * @dma_running: indicates whether DMA is in operation - * @cur_cs: current chip select (gpio) - * @chipselects: list of chipselects (gpios) + * @cur_cs: current chip select index + * @cur_gpio: current chip select GPIO line */ struct pl022 { struct amba_device *adev; @@ -398,7 +398,7 @@ struct pl022 { bool dma_running; #endif int cur_cs; - int *chipselects; + int cur_gpio; }; /** @@ -454,8 +454,8 @@ static void pl022_cs_control(struct pl022 *pl022, u32 command) { if (pl022->vendor->internal_cs_ctrl) internal_cs_control(pl022, command); - else if (gpio_is_valid(pl022->cur_cs)) - gpio_set_value(pl022->cur_cs, command); + else if (gpio_is_valid(pl022->cur_gpio)) + gpio_set_value(pl022->cur_gpio, command); } /** @@ -1580,7 +1580,9 @@ static int pl022_transfer_one_message(struct spi_master *master, /* Setup the SPI using the per chip configuration */ pl022->cur_chip = spi_get_ctldata(msg->spi); - pl022->cur_cs = pl022->chipselects[msg->spi->chip_select]; + pl022->cur_cs = msg->spi->chip_select; + /* This is always available but may be set to -ENOENT */ + pl022->cur_gpio = msg->spi->cs_gpio; restore_state(pl022); flush(pl022); @@ -1923,8 +1925,6 @@ static int pl022_setup(struct spi_device *spi) /* Now set controller state based on controller data */ chip->xfer_type = chip_info->com_mode; - if (!gpio_is_valid(pl022->chipselects[spi->chip_select])) - dev_warn(&spi->dev, "invalid chip select\n"); /* Check bits per word with vendor specific range */ if ((bits <= 3) || (bits > pl022->vendor->max_bpw)) { @@ -2072,7 +2072,6 @@ pl022_platform_data_dt_get(struct device *dev) { struct device_node *np = dev->of_node; struct pl022_ssp_controller *pd; - u32 tmp = 0; if (!np) { dev_err(dev, "no dt node defined\n"); @@ -2085,8 +2084,6 @@ pl022_platform_data_dt_get(struct device *dev) pd->bus_id = -1; pd->enable_dma = 1; - of_property_read_u32(np, "num-cs", &tmp); - pd->num_chipselect = tmp; of_property_read_u32(np, "pl022,autosuspend-delay", &pd->autosuspend_delay); pd->rt = of_property_read_bool(np, "pl022,rt"); @@ -2101,8 +2098,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) dev_get_platdata(&adev->dev); struct spi_master *master; struct pl022 *pl022 = NULL; /*Data for this driver */ - struct device_node *np = adev->dev.of_node; - int status = 0, i, num_cs; + int status = 0; dev_info(&adev->dev, "ARM PL022 driver, device ID: 0x%08x\n", adev->periphid); @@ -2114,13 +2110,6 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) return -ENODEV; } - if (platform_info->num_chipselect) { - num_cs = platform_info->num_chipselect; - } else { - dev_err(dev, "probe: no chip select defined\n"); - return -ENODEV; - } - /* Allocate master with space for data */ master = spi_alloc_master(dev, sizeof(struct pl022)); if (master == NULL) { @@ -2133,19 +2122,12 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) pl022->master_info = platform_info; pl022->adev = adev; pl022->vendor = id->data; - pl022->chipselects = devm_kcalloc(dev, num_cs, sizeof(int), - GFP_KERNEL); - if (!pl022->chipselects) { - status = -ENOMEM; - goto err_no_mem; - } /* * Bus Number Which has been Assigned to this SSP controller * on this board */ master->bus_num = platform_info->bus_id; - master->num_chipselect = num_cs; master->cleanup = pl022_cleanup; master->setup = pl022_setup; master->auto_runtime_pm = true; @@ -2154,36 +2136,6 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) master->rt = platform_info->rt; master->dev.of_node = dev->of_node; - if (platform_info->num_chipselect && platform_info->chipselects) { - for (i = 0; i < num_cs; i++) - pl022->chipselects[i] = platform_info->chipselects[i]; - } else if (pl022->vendor->internal_cs_ctrl) { - for (i = 0; i < num_cs; i++) - pl022->chipselects[i] = i; - } else if (IS_ENABLED(CONFIG_OF)) { - for (i = 0; i < num_cs; i++) { - int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); - - if (cs_gpio == -EPROBE_DEFER) { - status = -EPROBE_DEFER; - goto err_no_gpio; - } - - pl022->chipselects[i] = cs_gpio; - - if (gpio_is_valid(cs_gpio)) { - if (devm_gpio_request(dev, cs_gpio, "ssp-pl022")) - dev_err(&adev->dev, - "could not request %d gpio\n", - cs_gpio); - else if (gpio_direction_output(cs_gpio, 1)) - dev_err(&adev->dev, - "could not set gpio %d as output\n", - cs_gpio); - } - } - } - /* * Supports mode 0-3, loopback, and active low CS. Transfers are * always MS bit first on the original pl022. @@ -2286,8 +2238,6 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) err_no_ioremap: amba_release_regions(adev); err_no_ioregion: - err_no_gpio: - err_no_mem: spi_master_put(master); return status; } diff --git a/include/linux/amba/pl022.h b/include/linux/amba/pl022.h index 29274cedefdeda..9bf58aac0df2bb 100644 --- a/include/linux/amba/pl022.h +++ b/include/linux/amba/pl022.h @@ -223,10 +223,6 @@ struct dma_chan; /** * struct pl022_ssp_master - device.platform_data for SPI controller devices. * @bus_id: identifier for this bus - * @num_chipselect: chipselects are used to distinguish individual - * SPI slaves, and are numbered from zero to num_chipselects - 1. - * each slave has a chipselect signal, but it's common that not - * every chipselect is connected to a slave. * @enable_dma: if true enables DMA driven transfers. * @dma_rx_param: parameter to locate an RX DMA channel. * @dma_tx_param: parameter to locate a TX DMA channel. @@ -235,18 +231,15 @@ struct dma_chan; * indicates no delay and the device will be suspended immediately. * @rt: indicates the controller should run the message pump with realtime * priority to minimise the transfer latency on the bus. - * @chipselects: list of chip select gpios */ struct pl022_ssp_controller { u16 bus_id; - u8 num_chipselect; u8 enable_dma:1; bool (*dma_filter)(struct dma_chan *chan, void *filter_param); void *dma_rx_param; void *dma_tx_param; int autosuspend_delay; bool rt; - int *chipselects; }; /** From 8bb2dbf1e14d05e92a23e03bcbd1c27f7ee937f7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 30 Mar 2021 18:49:07 +0200 Subject: [PATCH 063/113] spi: pl022: Convert to use GPIO descriptors This converts the PL022 driver to use GPIO descriptors instead of the old global GPIO numberspace. Since the driver handles messages on its own it needs to manage the GPIO descriptor directly. Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20210330164907.2346010-3-linus.walleij@linaro.org Signed-off-by: Mark Brown --- drivers/spi/spi-pl022.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 680f9cdfe2955c..0c9e3f270f05a3 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -363,7 +362,7 @@ struct vendor_data { * @dummypage: a dummy page used for driving data on the bus with DMA * @dma_running: indicates whether DMA is in operation * @cur_cs: current chip select index - * @cur_gpio: current chip select GPIO line + * @cur_gpiod: current chip select GPIO descriptor */ struct pl022 { struct amba_device *adev; @@ -398,7 +397,7 @@ struct pl022 { bool dma_running; #endif int cur_cs; - int cur_gpio; + struct gpio_desc *cur_gpiod; }; /** @@ -454,8 +453,16 @@ static void pl022_cs_control(struct pl022 *pl022, u32 command) { if (pl022->vendor->internal_cs_ctrl) internal_cs_control(pl022, command); - else if (gpio_is_valid(pl022->cur_gpio)) - gpio_set_value(pl022->cur_gpio, command); + else if (pl022->cur_gpiod) + /* + * This needs to be inverted since with GPIOLIB in + * control, the inversion will be handled by + * GPIOLIB's active low handling. The "command" + * passed into this function will be SSP_CHIP_SELECT + * which is enum:ed to 0, so we need the inverse + * (1) to activate chip select. + */ + gpiod_set_value(pl022->cur_gpiod, !command); } /** @@ -1582,7 +1589,7 @@ static int pl022_transfer_one_message(struct spi_master *master, pl022->cur_chip = spi_get_ctldata(msg->spi); pl022->cur_cs = msg->spi->chip_select; /* This is always available but may be set to -ENOENT */ - pl022->cur_gpio = msg->spi->cs_gpio; + pl022->cur_gpiod = msg->spi->cs_gpiod; restore_state(pl022); flush(pl022); @@ -2135,6 +2142,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) master->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware; master->rt = platform_info->rt; master->dev.of_node = dev->of_node; + master->use_gpio_descriptors = true; /* * Supports mode 0-3, loopback, and active low CS. Transfers are From c770d8631e1810d8f1ce21b18ad5dd67eeb39e5c Mon Sep 17 00:00:00 2001 From: Jay Fang Date: Sat, 27 Mar 2021 17:10:00 +0800 Subject: [PATCH 064/113] spi: Add HiSilicon SPI Controller Driver for Kunpeng SoCs This driver supports SPI Controller for HiSilicon Kunpeng SoCs. This driver supports SPI operations using FIFO mode of transfer. DMA is not supported, and we just use IRQ mode for operation completion notification. Only ACPI firmware is supported. Signed-off-by: Jay Fang Link: https://lore.kernel.org/r/1616836200-45827-1-git-send-email-f.fangjian@huawei.com Signed-off-by: Mark Brown --- MAINTAINERS | 7 + drivers/spi/Kconfig | 10 + drivers/spi/Makefile | 1 + drivers/spi/spi-hisi-kunpeng.c | 505 +++++++++++++++++++++++++++++++++ 4 files changed, 523 insertions(+) create mode 100644 drivers/spi/spi-hisi-kunpeng.c diff --git a/MAINTAINERS b/MAINTAINERS index d92f85ca831d30..206305cc869b5b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8114,6 +8114,13 @@ F: drivers/crypto/hisilicon/sec2/sec_crypto.c F: drivers/crypto/hisilicon/sec2/sec_crypto.h F: drivers/crypto/hisilicon/sec2/sec_main.c +HISILICON SPI Controller DRIVER FOR KUNPENG SOCS +M: Jay Fang +L: linux-spi@vger.kernel.org +S: Maintained +W: http://www.hisilicon.com +F: drivers/spi/spi-hisi-kunpeng.c + HISILICON STAGING DRIVERS FOR HIKEY 960/970 M: Mauro Carvalho Chehab L: devel@driverdev.osuosl.org diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 09a263cf4ae2ed..853cf4c46e5e4a 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -332,6 +332,16 @@ config SPI_FSL_QUADSPI This controller does not support generic SPI messages. It only supports the high-level SPI memory interface. +config SPI_HISI_KUNPENG + tristate "HiSilicon SPI Controller for Kunpeng SoCs" + depends on (ARM64 && ACPI) || COMPILE_TEST + help + This enables support for HiSilicon SPI controller found on + Kunpeng SoCs. + + This driver can also be built as a module. If so, the module + will be called hisi-kunpeng-spi. + config SPI_HISI_SFC_V3XX tristate "HiSilicon SPI NOR Flash Controller for Hi16XX chipsets" depends on (ARM64 && ACPI) || COMPILE_TEST diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 0f06fc0813c616..29fee71022b41b 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_SPI_FSL_LPSPI) += spi-fsl-lpspi.o obj-$(CONFIG_SPI_FSL_QUADSPI) += spi-fsl-qspi.o obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o obj-$(CONFIG_SPI_GPIO) += spi-gpio.o +obj-$(CONFIG_SPI_HISI_KUNPENG) += spi-hisi-kunpeng.o obj-$(CONFIG_SPI_HISI_SFC_V3XX) += spi-hisi-sfc-v3xx.o obj-$(CONFIG_SPI_IMG_SPFI) += spi-img-spfi.o obj-$(CONFIG_SPI_IMX) += spi-imx.o diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c new file mode 100644 index 00000000000000..abc0cd54eee6b3 --- /dev/null +++ b/drivers/spi/spi-hisi-kunpeng.c @@ -0,0 +1,505 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// HiSilicon SPI Controller Driver for Kunpeng SoCs +// +// Copyright (c) 2021 HiSilicon Technologies Co., Ltd. +// Author: Jay Fang +// +// This code is based on spi-dw-core.c. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Register offsets */ +#define HISI_SPI_CSCR 0x00 /* cs control register */ +#define HISI_SPI_CR 0x04 /* spi common control register */ +#define HISI_SPI_ENR 0x08 /* spi enable register */ +#define HISI_SPI_FIFOC 0x0c /* fifo level control register */ +#define HISI_SPI_IMR 0x10 /* interrupt mask register */ +#define HISI_SPI_DIN 0x14 /* data in register */ +#define HISI_SPI_DOUT 0x18 /* data out register */ +#define HISI_SPI_SR 0x1c /* status register */ +#define HISI_SPI_RISR 0x20 /* raw interrupt status register */ +#define HISI_SPI_ISR 0x24 /* interrupt status register */ +#define HISI_SPI_ICR 0x28 /* interrupt clear register */ +#define HISI_SPI_VERSION 0xe0 /* version register */ + +/* Bit fields in HISI_SPI_CR */ +#define CR_LOOP_MASK GENMASK(1, 1) +#define CR_CPOL_MASK GENMASK(2, 2) +#define CR_CPHA_MASK GENMASK(3, 3) +#define CR_DIV_PRE_MASK GENMASK(11, 4) +#define CR_DIV_POST_MASK GENMASK(19, 12) +#define CR_BPW_MASK GENMASK(24, 20) +#define CR_SPD_MODE_MASK GENMASK(25, 25) + +/* Bit fields in HISI_SPI_FIFOC */ +#define FIFOC_TX_MASK GENMASK(5, 3) +#define FIFOC_RX_MASK GENMASK(11, 9) + +/* Bit fields in HISI_SPI_IMR, 4 bits */ +#define IMR_RXOF BIT(0) /* Receive Overflow */ +#define IMR_RXTO BIT(1) /* Receive Timeout */ +#define IMR_RX BIT(2) /* Receive */ +#define IMR_TX BIT(3) /* Transmit */ +#define IMR_MASK (IMR_RXOF | IMR_RXTO | IMR_RX | IMR_TX) + +/* Bit fields in HISI_SPI_SR, 5 bits */ +#define SR_TXE BIT(0) /* Transmit FIFO empty */ +#define SR_TXNF BIT(1) /* Transmit FIFO not full */ +#define SR_RXNE BIT(2) /* Receive FIFO not empty */ +#define SR_RXF BIT(3) /* Receive FIFO full */ +#define SR_BUSY BIT(4) /* Busy Flag */ + +/* Bit fields in HISI_SPI_ISR, 4 bits */ +#define ISR_RXOF BIT(0) /* Receive Overflow */ +#define ISR_RXTO BIT(1) /* Receive Timeout */ +#define ISR_RX BIT(2) /* Receive */ +#define ISR_TX BIT(3) /* Transmit */ +#define ISR_MASK (ISR_RXOF | ISR_RXTO | ISR_RX | ISR_TX) + +/* Bit fields in HISI_SPI_ICR, 2 bits */ +#define ICR_RXOF BIT(0) /* Receive Overflow */ +#define ICR_RXTO BIT(1) /* Receive Timeout */ +#define ICR_MASK (ICR_RXOF | ICR_RXTO) + +#define DIV_POST_MAX 0xFF +#define DIV_POST_MIN 0x00 +#define DIV_PRE_MAX 0xFE +#define DIV_PRE_MIN 0x02 +#define CLK_DIV_MAX ((1 + DIV_POST_MAX) * DIV_PRE_MAX) +#define CLK_DIV_MIN ((1 + DIV_POST_MIN) * DIV_PRE_MIN) + +#define DEFAULT_NUM_CS 1 + +#define HISI_SPI_WAIT_TIMEOUT_MS 10UL + +enum hisi_spi_rx_level_trig { + HISI_SPI_RX_1, + HISI_SPI_RX_4, + HISI_SPI_RX_8, + HISI_SPI_RX_16, + HISI_SPI_RX_32, + HISI_SPI_RX_64, + HISI_SPI_RX_128 +}; + +enum hisi_spi_tx_level_trig { + HISI_SPI_TX_1_OR_LESS, + HISI_SPI_TX_4_OR_LESS, + HISI_SPI_TX_8_OR_LESS, + HISI_SPI_TX_16_OR_LESS, + HISI_SPI_TX_32_OR_LESS, + HISI_SPI_TX_64_OR_LESS, + HISI_SPI_TX_128_OR_LESS +}; + +enum hisi_spi_frame_n_bytes { + HISI_SPI_N_BYTES_NULL, + HISI_SPI_N_BYTES_U8, + HISI_SPI_N_BYTES_U16, + HISI_SPI_N_BYTES_U32 = 4 +}; + +/* Slave spi_dev related */ +struct hisi_chip_data { + u32 cr; + u32 speed_hz; /* baud rate */ + u16 clk_div; /* baud rate divider */ + + /* clk_div = (1 + div_post) * div_pre */ + u8 div_post; /* value from 0 to 255 */ + u8 div_pre; /* value from 2 to 254 (even only!) */ +}; + +struct hisi_spi { + struct device *dev; + + void __iomem *regs; + int irq; + u32 fifo_len; /* depth of the FIFO buffer */ + + /* Current message transfer state info */ + const void *tx; + unsigned int tx_len; + void *rx; + unsigned int rx_len; + u8 n_bytes; /* current is a 1/2/4 bytes op */ +}; + +static u32 hisi_spi_busy(struct hisi_spi *hs) +{ + return readl(hs->regs + HISI_SPI_SR) & SR_BUSY; +} + +static u32 hisi_spi_rx_not_empty(struct hisi_spi *hs) +{ + return readl(hs->regs + HISI_SPI_SR) & SR_RXNE; +} + +static u32 hisi_spi_tx_not_full(struct hisi_spi *hs) +{ + return readl(hs->regs + HISI_SPI_SR) & SR_TXNF; +} + +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)) + readl(hs->regs + HISI_SPI_DOUT); + } while (hisi_spi_busy(hs) && limit--); +} + +/* Disable the controller and all interrupts */ +static void hisi_spi_disable(struct hisi_spi *hs) +{ + writel(0, hs->regs + HISI_SPI_ENR); + writel(IMR_MASK, hs->regs + HISI_SPI_IMR); + writel(ICR_MASK, hs->regs + HISI_SPI_ICR); +} + +static u8 hisi_spi_n_bytes(struct spi_transfer *transfer) +{ + if (transfer->bits_per_word <= 8) + return HISI_SPI_N_BYTES_U8; + else if (transfer->bits_per_word <= 16) + return HISI_SPI_N_BYTES_U16; + else + return HISI_SPI_N_BYTES_U32; +} + +static void hisi_spi_reader(struct hisi_spi *hs) +{ + u32 max = min_t(u32, hs->rx_len, hs->fifo_len); + u32 rxw; + + while (hisi_spi_rx_not_empty(hs) && max--) { + rxw = readl(hs->regs + HISI_SPI_DOUT); + /* Check the transfer's original "rx" is not null */ + if (hs->rx) { + switch (hs->n_bytes) { + case HISI_SPI_N_BYTES_U8: + *(u8 *)(hs->rx) = rxw; + break; + case HISI_SPI_N_BYTES_U16: + *(u16 *)(hs->rx) = rxw; + break; + case HISI_SPI_N_BYTES_U32: + *(u32 *)(hs->rx) = rxw; + break; + } + hs->rx += hs->n_bytes; + } + --hs->rx_len; + } +} + +static void hisi_spi_writer(struct hisi_spi *hs) +{ + u32 max = min_t(u32, hs->tx_len, hs->fifo_len); + u32 txw = 0; + + while (hisi_spi_tx_not_full(hs) && max--) { + /* Check the transfer's original "tx" is not null */ + if (hs->tx) { + switch (hs->n_bytes) { + case HISI_SPI_N_BYTES_U8: + txw = *(u8 *)(hs->tx); + break; + case HISI_SPI_N_BYTES_U16: + txw = *(u16 *)(hs->tx); + break; + case HISI_SPI_N_BYTES_U32: + txw = *(u32 *)(hs->tx); + break; + } + hs->tx += hs->n_bytes; + } + writel(txw, hs->regs + HISI_SPI_DIN); + --hs->tx_len; + } +} + +static void __hisi_calc_div_reg(struct hisi_chip_data *chip) +{ + chip->div_pre = DIV_PRE_MAX; + while (chip->div_pre >= DIV_PRE_MIN) { + if (chip->clk_div % chip->div_pre == 0) + break; + + chip->div_pre -= 2; + } + + if (chip->div_pre > chip->clk_div) + chip->div_pre = chip->clk_div; + + chip->div_post = (chip->clk_div / chip->div_pre) - 1; +} + +static u32 hisi_calc_effective_speed(struct spi_controller *master, + struct hisi_chip_data *chip, u32 speed_hz) +{ + u32 effective_speed; + + /* Note clock divider doesn't support odd numbers */ + chip->clk_div = DIV_ROUND_UP(master->max_speed_hz, speed_hz) + 1; + chip->clk_div &= 0xfffe; + if (chip->clk_div > CLK_DIV_MAX) + chip->clk_div = CLK_DIV_MAX; + + effective_speed = master->max_speed_hz / chip->clk_div; + if (chip->speed_hz != effective_speed) { + __hisi_calc_div_reg(chip); + chip->speed_hz = effective_speed; + } + + return effective_speed; +} + +static u32 hisi_spi_prepare_cr(struct spi_device *spi) +{ + u32 cr = FIELD_PREP(CR_SPD_MODE_MASK, 1); + + cr |= FIELD_PREP(CR_CPHA_MASK, (spi->mode & SPI_CPHA) ? 1 : 0); + cr |= FIELD_PREP(CR_CPOL_MASK, (spi->mode & SPI_CPOL) ? 1 : 0); + cr |= FIELD_PREP(CR_LOOP_MASK, (spi->mode & SPI_LOOP) ? 1 : 0); + + return cr; +} + +static void hisi_spi_hw_init(struct hisi_spi *hs) +{ + hisi_spi_disable(hs); + + /* FIFO default config */ + writel(FIELD_PREP(FIFOC_TX_MASK, HISI_SPI_TX_64_OR_LESS) | + FIELD_PREP(FIFOC_RX_MASK, HISI_SPI_RX_16), + hs->regs + HISI_SPI_FIFOC); + + hs->fifo_len = 256; +} + +static irqreturn_t hisi_spi_irq(int irq, void *dev_id) +{ + struct spi_controller *master = dev_id; + struct hisi_spi *hs = spi_controller_get_devdata(master); + u32 irq_status = readl(hs->regs + HISI_SPI_ISR) & ISR_MASK; + + if (!irq_status) + return IRQ_NONE; + + if (!master->cur_msg) + return IRQ_HANDLED; + + /* Error handling */ + if (irq_status & ISR_RXOF) { + dev_err(hs->dev, "interrupt_transfer: fifo overflow\n"); + master->cur_msg->status = -EIO; + goto finalize_transfer; + } + + /* + * Read data from the Rx FIFO every time. If there is + * nothing left to receive, finalize the transfer. + */ + hisi_spi_reader(hs); + if (!hs->rx_len) + goto finalize_transfer; + + /* Send data out when Tx FIFO IRQ triggered */ + if (irq_status & ISR_TX) + hisi_spi_writer(hs); + + return IRQ_HANDLED; + +finalize_transfer: + hisi_spi_disable(hs); + spi_finalize_current_transfer(master); + return IRQ_HANDLED; +} + +static int hisi_spi_transfer_one(struct spi_controller *master, + struct spi_device *spi, struct spi_transfer *transfer) +{ + struct hisi_spi *hs = spi_controller_get_devdata(master); + struct hisi_chip_data *chip = spi_get_ctldata(spi); + u32 cr = chip->cr; + + /* Update per transfer options for speed and bpw */ + transfer->effective_speed_hz = + hisi_calc_effective_speed(master, chip, transfer->speed_hz); + cr |= FIELD_PREP(CR_DIV_PRE_MASK, chip->div_pre); + cr |= FIELD_PREP(CR_DIV_POST_MASK, chip->div_post); + cr |= FIELD_PREP(CR_BPW_MASK, transfer->bits_per_word - 1); + writel(cr, hs->regs + HISI_SPI_CR); + + hisi_spi_flush_fifo(hs); + + hs->n_bytes = hisi_spi_n_bytes(transfer); + hs->tx = transfer->tx_buf; + hs->tx_len = transfer->len / hs->n_bytes; + hs->rx = transfer->rx_buf; + hs->rx_len = hs->tx_len; + + /* + * Ensure that the transfer data above has been updated + * before the interrupt to start. + */ + smp_mb(); + + /* Enable all interrupts and the controller */ + writel(~IMR_MASK, hs->regs + HISI_SPI_IMR); + writel(1, hs->regs + HISI_SPI_ENR); + + return 1; +} + +static void hisi_spi_handle_err(struct spi_controller *master, + struct spi_message *msg) +{ + struct hisi_spi *hs = spi_controller_get_devdata(master); + + hisi_spi_disable(hs); + + /* + * Wait for interrupt handler that is + * already in timeout to complete. + */ + msleep(HISI_SPI_WAIT_TIMEOUT_MS); +} + +static int hisi_spi_setup(struct spi_device *spi) +{ + struct hisi_chip_data *chip; + + /* Only alloc on first setup */ + chip = spi_get_ctldata(spi); + if (!chip) { + chip = kzalloc(sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + spi_set_ctldata(spi, chip); + } + + chip->cr = hisi_spi_prepare_cr(spi); + + return 0; +} + +static void hisi_spi_cleanup(struct spi_device *spi) +{ + struct hisi_chip_data *chip = spi_get_ctldata(spi); + + kfree(chip); + spi_set_ctldata(spi, NULL); +} + +static int hisi_spi_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct spi_controller *master; + struct hisi_spi *hs; + int ret, irq; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + master = devm_spi_alloc_master(dev, sizeof(*hs)); + if (!master) + return -ENOMEM; + + platform_set_drvdata(pdev, master); + + hs = spi_controller_get_devdata(master); + hs->dev = dev; + hs->irq = irq; + + hs->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(hs->regs)) + return PTR_ERR(hs->regs); + + /* Specify maximum SPI clocking speed (master only) by firmware */ + ret = device_property_read_u32(dev, "spi-max-frequency", + &master->max_speed_hz); + if (ret) { + dev_err(dev, "failed to get max SPI clocking speed, ret=%d\n", + ret); + return -EINVAL; + } + + ret = device_property_read_u16(dev, "num-cs", + &master->num_chipselect); + if (ret) + master->num_chipselect = DEFAULT_NUM_CS; + + master->use_gpio_descriptors = true; + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); + master->bus_num = pdev->id; + master->setup = hisi_spi_setup; + master->cleanup = hisi_spi_cleanup; + master->transfer_one = hisi_spi_transfer_one; + master->handle_err = hisi_spi_handle_err; + master->dev.fwnode = dev->fwnode; + + hisi_spi_hw_init(hs); + + ret = devm_request_irq(dev, hs->irq, hisi_spi_irq, 0, dev_name(dev), + master); + if (ret < 0) { + dev_err(dev, "failed to get IRQ=%d, ret=%d\n", hs->irq, ret); + return ret; + } + + ret = spi_register_controller(master); + if (ret) { + dev_err(dev, "failed to register spi master, ret=%d\n", ret); + return ret; + } + + dev_info(dev, "hw version:0x%x max-freq:%u kHz\n", + readl(hs->regs + HISI_SPI_VERSION), + master->max_speed_hz / 1000); + + return 0; +} + +static int hisi_spi_remove(struct platform_device *pdev) +{ + struct spi_controller *master = platform_get_drvdata(pdev); + + spi_unregister_controller(master); + + return 0; +} + +static const struct acpi_device_id hisi_spi_acpi_match[] = { + {"HISI03E1", 0}, + {} +}; +MODULE_DEVICE_TABLE(acpi, hisi_spi_acpi_match); + +static struct platform_driver hisi_spi_driver = { + .probe = hisi_spi_probe, + .remove = hisi_spi_remove, + .driver = { + .name = "hisi-kunpeng-spi", + .acpi_match_table = hisi_spi_acpi_match, + }, +}; +module_platform_driver(hisi_spi_driver); + +MODULE_AUTHOR("Jay Fang "); +MODULE_DESCRIPTION("HiSilicon SPI Controller Driver for Kunpeng SoCs"); +MODULE_LICENSE("GPL v2"); From e54338004c032b0bb556c7a56db8688454b6587e Mon Sep 17 00:00:00 2001 From: Ramuthevar Vadivel Murugan Date: Fri, 26 Mar 2021 18:30:34 +0530 Subject: [PATCH 065/113] spi: Convert cadence-quadspi.txt to cadence-quadspi.yaml There is no way as of now to have a parent or bus defining properties for child nodes. For now, avoid it in the example to silence warnings on dt_schema_check. We can figure out how to deal with actual dts files later. [p.yadav@ti.com: Fix how compatible is defined, make reset optional, fix minor typos, remove subnode properties in example, update commit message.] Signed-off-by: Ramuthevar Vadivel Murugan Signed-off-by: Pratyush Yadav Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20210326130034.15231-5-p.yadav@ti.com Signed-off-by: Mark Brown --- .../bindings/spi/cadence-quadspi.txt | 68 --------- .../bindings/spi/cdns,qspi-nor.yaml | 143 ++++++++++++++++++ 2 files changed, 143 insertions(+), 68 deletions(-) delete mode 100644 Documentation/devicetree/bindings/spi/cadence-quadspi.txt create mode 100644 Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml diff --git a/Documentation/devicetree/bindings/spi/cadence-quadspi.txt b/Documentation/devicetree/bindings/spi/cadence-quadspi.txt deleted file mode 100644 index 8ace832a2d80ce..00000000000000 --- a/Documentation/devicetree/bindings/spi/cadence-quadspi.txt +++ /dev/null @@ -1,68 +0,0 @@ -* Cadence Quad SPI controller - -Required properties: -- compatible : should be one of the following: - Generic default - "cdns,qspi-nor". - For TI 66AK2G SoC - "ti,k2g-qspi", "cdns,qspi-nor". - For TI AM654 SoC - "ti,am654-ospi", "cdns,qspi-nor". - For Intel LGM SoC - "intel,lgm-qspi", "cdns,qspi-nor". -- reg : Contains two entries, each of which is a tuple consisting of a - physical address and length. The first entry is the address and - length of the controller register set. The second entry is the - address and length of the QSPI Controller data area. -- interrupts : Unit interrupt specifier for the controller interrupt. -- clocks : phandle to the Quad SPI clock. -- cdns,fifo-depth : Size of the data FIFO in words. -- cdns,fifo-width : Bus width of the data FIFO in bytes. -- cdns,trigger-address : 32-bit indirect AHB trigger address. - -Optional properties: -- cdns,is-decoded-cs : Flag to indicate whether decoder is used or not. -- cdns,rclk-en : Flag to indicate that QSPI return clock is used to latch - the read data rather than the QSPI clock. Make sure that QSPI return - clock is populated on the board before using this property. - -Optional subnodes: -Subnodes of the Cadence Quad SPI controller are spi slave nodes with additional -custom properties: -- cdns,read-delay : Delay for read capture logic, in clock cycles -- cdns,tshsl-ns : Delay in nanoseconds for the length that the master - mode chip select outputs are de-asserted between - transactions. -- cdns,tsd2d-ns : Delay in nanoseconds between one chip select being - de-activated and the activation of another. -- cdns,tchsh-ns : Delay in nanoseconds between last bit of current - transaction and deasserting the device chip select - (qspi_n_ss_out). -- cdns,tslch-ns : Delay in nanoseconds between setting qspi_n_ss_out low - and first bit transfer. -- resets : Must contain an entry for each entry in reset-names. - See ../reset/reset.txt for details. -- reset-names : Must include either "qspi" and/or "qspi-ocp". - -Example: - - qspi: spi@ff705000 { - compatible = "cdns,qspi-nor"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0xff705000 0x1000>, - <0xffa00000 0x1000>; - interrupts = <0 151 4>; - clocks = <&qspi_clk>; - cdns,is-decoded-cs; - cdns,fifo-depth = <128>; - cdns,fifo-width = <4>; - cdns,trigger-address = <0x00000000>; - resets = <&rst QSPI_RESET>, <&rst QSPI_OCP_RESET>; - reset-names = "qspi", "qspi-ocp"; - - flash0: n25q00@0 { - ... - cdns,read-delay = <4>; - cdns,tshsl-ns = <50>; - cdns,tsd2d-ns = <50>; - cdns,tchsh-ns = <4>; - cdns,tslch-ns = <4>; - }; - }; diff --git a/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml b/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml new file mode 100644 index 00000000000000..0e7087cc8bf95e --- /dev/null +++ b/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml @@ -0,0 +1,143 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/cdns,qspi-nor.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Cadence Quad SPI controller + +maintainers: + - Pratyush Yadav + +allOf: + - $ref: spi-controller.yaml# + +properties: + compatible: + oneOf: + - items: + - enum: + - ti,k2g-qspi + - ti,am654-ospi + - intel,lgm-qspi + - const: cdns,qspi-nor + - const: cdns,qspi-nor + + reg: + items: + - description: the controller register set + - description: the controller data area + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + cdns,fifo-depth: + description: + Size of the data FIFO in words. + $ref: "/schemas/types.yaml#/definitions/uint32" + enum: [ 128, 256 ] + default: 128 + + cdns,fifo-width: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Bus width of the data FIFO in bytes. + default: 4 + + cdns,trigger-address: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + 32-bit indirect AHB trigger address. + + cdns,is-decoded-cs: + type: boolean + description: + Flag to indicate whether decoder is used to select different chip select + for different memory regions. + + cdns,rclk-en: + type: boolean + description: + Flag to indicate that QSPI return clock is used to latch the read + data rather than the QSPI clock. Make sure that QSPI return clock + is populated on the board before using this property. + + resets: + maxItems: 2 + + reset-names: + minItems: 1 + maxItems: 2 + items: + enum: [ qspi, qspi-ocp ] + +# subnode's properties +patternProperties: + "@[0-9a-f]+$": + type: object + description: + Flash device uses the below defined properties in the subnode. + + properties: + cdns,read-delay: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Delay for read capture logic, in clock cycles. + + cdns,tshsl-ns: + description: + Delay in nanoseconds for the length that the master mode chip select + outputs are de-asserted between transactions. + + cdns,tsd2d-ns: + description: + Delay in nanoseconds between one chip select being de-activated + and the activation of another. + + cdns,tchsh-ns: + description: + Delay in nanoseconds between last bit of current transaction and + deasserting the device chip select (qspi_n_ss_out). + + cdns,tslch-ns: + description: + Delay in nanoseconds between setting qspi_n_ss_out low and + first bit transfer. + +required: + - compatible + - reg + - interrupts + - clocks + - cdns,fifo-depth + - cdns,fifo-width + - cdns,trigger-address + - '#address-cells' + - '#size-cells' + +unevaluatedProperties: false + +examples: + - | + qspi: spi@ff705000 { + compatible = "cdns,qspi-nor"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xff705000 0x1000>, + <0xffa00000 0x1000>; + interrupts = <0 151 4>; + clocks = <&qspi_clk>; + cdns,fifo-depth = <128>; + cdns,fifo-width = <4>; + cdns,trigger-address = <0x00000000>; + resets = <&rst 0x1>, <&rst 0x2>; + reset-names = "qspi", "qspi-ocp"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0x0>; + }; + }; From d6644a1c2e17febf261fd692bb32271e5779bbd2 Mon Sep 17 00:00:00 2001 From: Wan Jiabing Date: Thu, 1 Apr 2021 14:59:04 +0800 Subject: [PATCH 066/113] spi: Remove repeated struct declaration struct spi_transfer is declared twice. One is declared at 24th line. The blew one is not needed though. Remove the duplicate. Signed-off-by: Wan Jiabing Link: https://lore.kernel.org/r/20210401065904.994121-1-wanjiabing@vivo.com Signed-off-by: Mark Brown --- include/linux/spi/spi.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 6d5b1866cc8914..4b192e74f024b9 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -247,7 +247,6 @@ static inline void *spi_get_drvdata(struct spi_device *spi) } struct spi_message; -struct spi_transfer; /** * struct spi_driver - Host side "protocol" driver From 9a446cf97af70ee81ba177703b67ac4955a5edcc Mon Sep 17 00:00:00 2001 From: Jay Fang Date: Wed, 7 Apr 2021 10:31:00 +0800 Subject: [PATCH 067/113] spi: hisi-kunpeng: Fix Woverflow warning on conversion Fix warning Woverflow on type conversion reported on x86_64: drivers/spi/spi-hisi-kunpeng.c:361:9: warning: conversion from 'long unsigned int' to 'u32' {aka 'unsigned int'} changes value from '18446744073709551600' to '4294967280' [-Woverflow] The registers are 32 bit, so fix by casting to u32. Fixes: c770d8631e18 ("spi: Add HiSilicon SPI Controller Driver for Kunpeng SoCs") Cc: Stephen Rothwell Reported-by: kernel test robot Signed-off-by: Jay Fang Link: https://lore.kernel.org/r/1617762660-54681-1-git-send-email-f.fangjian@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-hisi-kunpeng.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c index abc0cd54eee6b3..3f986ba1c328c5 100644 --- a/drivers/spi/spi-hisi-kunpeng.c +++ b/drivers/spi/spi-hisi-kunpeng.c @@ -358,7 +358,7 @@ static int hisi_spi_transfer_one(struct spi_controller *master, smp_mb(); /* Enable all interrupts and the controller */ - writel(~IMR_MASK, hs->regs + HISI_SPI_IMR); + writel(~(u32)IMR_MASK, hs->regs + HISI_SPI_IMR); writel(1, hs->regs + HISI_SPI_ENR); return 1; From 0e6521f13c297de32906ad7f691905803b2b2880 Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Thu, 1 Apr 2021 14:24:48 +0800 Subject: [PATCH 068/113] spi: orion: Use device_get_match_data() helper Use the device_get_match_data() helper instead of open coding. Signed-off-by: Tian Tao Link: https://lore.kernel.org/r/1617258288-1490-1-git-send-email-tiantao6@hisilicon.com Signed-off-by: Mark Brown --- drivers/spi/spi-orion.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 68ed7fd642569d..d02c5c9def20ce 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -634,7 +634,6 @@ MODULE_DEVICE_TABLE(of, orion_spi_of_match_table); static int orion_spi_probe(struct platform_device *pdev) { - const struct of_device_id *of_id; const struct orion_spi_dev *devdata; struct spi_master *master; struct orion_spi *spi; @@ -676,9 +675,8 @@ static int orion_spi_probe(struct platform_device *pdev) spi->master = master; spi->dev = &pdev->dev; - of_id = of_match_device(orion_spi_of_match_table, &pdev->dev); - devdata = (of_id) ? of_id->data : &orion_spi_dev_data; - spi->devdata = devdata; + devdata = device_get_match_data(&pdev->dev); + spi->devdata = devdata ? devdata : &orion_spi_dev_data; spi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(spi->clk)) { From a21fbc42807b15b74b0891bd557063e6acf4fcae Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Thu, 8 Apr 2021 17:25:59 +0800 Subject: [PATCH 069/113] spi: spi-zynqmp-gqspi: Fix runtime PM imbalance in zynqmp_qspi_probe When platform_get_irq() fails, a pairing PM usage counter increment is needed to keep the counter balanced. It's the same for the following error paths. Signed-off-by: Dinghao Liu Link: https://lore.kernel.org/r/20210408092559.3824-1-dinghao.liu@zju.edu.cn Signed-off-by: Mark Brown --- drivers/spi/spi-zynqmp-gqspi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index c8fa6ee18ae77b..95963a2de64aae 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -1197,6 +1197,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) return 0; clk_dis_all: + pm_runtime_get_noresume(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_runtime_disable(&pdev->dev); clk_disable_unprepare(xqspi->refclk); From 794aaf01444d4e765e2b067cba01cc69c1c68ed9 Mon Sep 17 00:00:00 2001 From: "William A. Kennington III" Date: Wed, 7 Apr 2021 02:55:27 -0700 Subject: [PATCH 070/113] spi: Fix use-after-free with devm_spi_alloc_* We can't rely on the contents of the devres list during spi_unregister_controller(), as the list is already torn down at the time we perform devres_find() for devm_spi_release_controller. This causes devices registered with devm_spi_alloc_{master,slave}() to be mistakenly identified as legacy, non-devm managed devices and have their reference counters decremented below 0. ------------[ cut here ]------------ WARNING: CPU: 1 PID: 660 at lib/refcount.c:28 refcount_warn_saturate+0x108/0x174 [] (refcount_warn_saturate) from [] (kobject_put+0x90/0x98) [] (kobject_put) from [] (put_device+0x20/0x24) r4:b6700140 [] (put_device) from [] (devm_spi_release_controller+0x3c/0x40) [] (devm_spi_release_controller) from [] (release_nodes+0x84/0xc4) r5:b6700180 r4:b6700100 [] (release_nodes) from [] (devres_release_all+0x5c/0x60) r8:b1638c54 r7:b117ad94 r6:b1638c10 r5:b117ad94 r4:b163dc10 [] (devres_release_all) from [] (__device_release_driver+0x144/0x1ec) r5:b117ad94 r4:b163dc10 [] (__device_release_driver) from [] (device_driver_detach+0x84/0xa0) r9:00000000 r8:00000000 r7:b117ad94 r6:b163dc54 r5:b1638c10 r4:b163dc10 [] (device_driver_detach) from [] (unbind_store+0xe4/0xf8) Instead, determine the devm allocation state as a flag on the controller which is guaranteed to be stable during cleanup. Fixes: 5e844cc37a5c ("spi: Introduce device-managed SPI controller allocation") Signed-off-by: William A. Kennington III Link: https://lore.kernel.org/r/20210407095527.2771582-1-wak@google.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 9 ++------- include/linux/spi/spi.h | 3 +++ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index b08efe88ccd6c3..904a353798b647 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2496,6 +2496,7 @@ struct spi_controller *__devm_spi_alloc_controller(struct device *dev, ctlr = __spi_alloc_controller(dev, size, slave); if (ctlr) { + ctlr->devm_allocated = true; *ptr = ctlr; devres_add(dev, ptr); } else { @@ -2842,11 +2843,6 @@ int devm_spi_register_controller(struct device *dev, } EXPORT_SYMBOL_GPL(devm_spi_register_controller); -static int devm_spi_match_controller(struct device *dev, void *res, void *ctlr) -{ - return *(struct spi_controller **)res == ctlr; -} - static int __unregister(struct device *dev, void *null) { spi_unregister_device(to_spi_device(dev)); @@ -2893,8 +2889,7 @@ void spi_unregister_controller(struct spi_controller *ctlr) /* Release the last reference on the controller if its driver * has not yet been converted to devm_spi_alloc_master/slave(). */ - if (!devres_find(ctlr->dev.parent, devm_spi_release_controller, - devm_spi_match_controller, ctlr)) + if (!ctlr->devm_allocated) put_device(&ctlr->dev); /* free bus id */ diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 592897fa4f030e..643139b1eafea7 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -510,6 +510,9 @@ struct spi_controller { #define SPI_MASTER_GPIO_SS BIT(5) /* GPIO CS must select slave */ + /* flag indicating this is a non-devres managed controller */ + bool devm_allocated; + /* flag indicating this is an SPI slave controller */ bool slave; From d570838efb6fb3154cbd08ab1b22d1f6442b1e78 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 8 Apr 2021 09:50:45 +0200 Subject: [PATCH 071/113] ARM/spi: spear: Drop PL022 num_chipselect A previous refactoring moved the chip select number handling to the SPI core and we missed a leftover platform data user in the ST spear platform. The spear is not using this chipselect or PL022 for anything and should be using device tree like the rest of the platform so just delete the offending platform data. Cc: Viresh Kumar Cc: Shiraz Hashim Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Linus Walleij Acked-by: Viresh Kumar Link: https://lore.kernel.org/r/20210408075045.3435046-1-linus.walleij@linaro.org Signed-off-by: Mark Brown --- arch/arm/mach-spear/spear320.c | 2 -- arch/arm/mach-spear/spear3xx.c | 10 ---------- 2 files changed, 12 deletions(-) diff --git a/arch/arm/mach-spear/spear320.c b/arch/arm/mach-spear/spear320.c index 0958f68a21e236..926d5a243238af 100644 --- a/arch/arm/mach-spear/spear320.c +++ b/arch/arm/mach-spear/spear320.c @@ -195,14 +195,12 @@ static struct pl022_ssp_controller spear320_ssp_data[] = { .dma_filter = pl08x_filter_id, .dma_tx_param = "ssp1_tx", .dma_rx_param = "ssp1_rx", - .num_chipselect = 2, }, { .bus_id = 2, .enable_dma = 1, .dma_filter = pl08x_filter_id, .dma_tx_param = "ssp2_tx", .dma_rx_param = "ssp2_rx", - .num_chipselect = 2, } }; diff --git a/arch/arm/mach-spear/spear3xx.c b/arch/arm/mach-spear/spear3xx.c index 8537fcffe5a86e..f83321d5e35383 100644 --- a/arch/arm/mach-spear/spear3xx.c +++ b/arch/arm/mach-spear/spear3xx.c @@ -30,16 +30,6 @@ struct pl022_ssp_controller pl022_plat_data = { .dma_filter = pl08x_filter_id, .dma_tx_param = "ssp0_tx", .dma_rx_param = "ssp0_rx", - /* - * This is number of spi devices that can be connected to spi. There are - * two type of chipselects on which slave devices can work. One is chip - * select provided by spi masters other is controlled through external - * gpio's. We can't use chipselect provided from spi master (because as - * soon as FIFO becomes empty, CS is disabled and transfer ends). So - * this number now depends on number of gpios available for spi. each - * slave on each master requires a separate gpio pin. - */ - .num_chipselect = 2, }; /* dmac device registration */ From 5fed9fe5b41aea58e5b32be506dc50c9ab9a0e4d Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Thu, 1 Apr 2021 22:03:50 +0800 Subject: [PATCH 072/113] spi: fsl: add missing iounmap() on error in of_fsl_spi_probe() Add the missing iounmap() before return from of_fsl_spi_probe() in the error handling case. Fixes: 0f0581b24bd0 ("spi: fsl: Convert to use CS GPIO descriptors") Reported-by: Hulk Robot Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20210401140350.1677925-1-yangyingliang@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-spi.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index e4a8d203f94081..d0e5aa18b7bad7 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -707,6 +707,11 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) struct resource mem; int irq, type; int ret; + bool spisel_boot = false; +#if IS_ENABLED(CONFIG_FSL_SOC) + struct mpc8xxx_spi_probe_info *pinfo = NULL; +#endif + ret = of_mpc8xxx_spi_probe(ofdev); if (ret) @@ -715,9 +720,8 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) type = fsl_spi_get_type(&ofdev->dev); if (type == TYPE_FSL) { struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); - bool spisel_boot = false; #if IS_ENABLED(CONFIG_FSL_SOC) - struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); + pinfo = to_of_pinfo(pdata); spisel_boot = of_property_read_bool(np, "fsl,spisel_boot"); if (spisel_boot) { @@ -746,15 +750,24 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) ret = of_address_to_resource(np, 0, &mem); if (ret) - return ret; + goto unmap_out; irq = platform_get_irq(ofdev, 0); - if (irq < 0) - return irq; + if (irq < 0) { + ret = irq; + goto unmap_out; + } master = fsl_spi_probe(dev, &mem, irq); return PTR_ERR_OR_ZERO(master); + +unmap_out: +#if IS_ENABLED(CONFIG_FSL_SOC) + if (spisel_boot) + iounmap(pinfo->immr_spi_cs); +#endif + return ret; } static int of_fsl_spi_remove(struct platform_device *ofdev) From a16bff68b75fd082d36aa0b14b540bd7a3ebebbd Mon Sep 17 00:00:00 2001 From: Quanyang Wang Date: Thu, 8 Apr 2021 12:02:20 +0800 Subject: [PATCH 073/113] spi: spi-zynqmp-gqspi: use wait_for_completion_timeout to make zynqmp_qspi_exec_op not interruptible When Ctrl+C occurs during the process of zynqmp_qspi_exec_op, the function wait_for_completion_interruptible_timeout will return a non-zero value -ERESTARTSYS immediately. This will disrupt the SPI memory operation because the data transmitting may begin before the command or address transmitting completes. Use wait_for_completion_timeout to prevent the process from being interruptible. This patch fixes the error as below: root@xilinx-zynqmp:~# flash_erase /dev/mtd3 0 0 Erasing 4 Kibyte @ 3d000 -- 4 % complete (Press Ctrl+C) [ 169.581911] zynqmp-qspi ff0f0000.spi: Chip select timed out [ 170.585907] zynqmp-qspi ff0f0000.spi: Chip select timed out [ 171.589910] zynqmp-qspi ff0f0000.spi: Chip select timed out [ 172.593910] zynqmp-qspi ff0f0000.spi: Chip select timed out [ 173.597907] zynqmp-qspi ff0f0000.spi: Chip select timed out [ 173.603480] spi-nor spi0.0: Erase operation failed. [ 173.608368] spi-nor spi0.0: Attempted to modify a protected sector. Fixes: 1c26372e5aa9 ("spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework") Signed-off-by: Quanyang Wang Reviewed-by: Amit Kumar Mahapatra Link: https://lore.kernel.org/r/20210408040223.23134-2-quanyang.wang@windriver.com Signed-off-by: Mark Brown --- drivers/spi/spi-zynqmp-gqspi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index c8fa6ee18ae77b..d49ab657555373 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -973,7 +973,7 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem, zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST, GQSPI_IER_GENFIFOEMPTY_MASK | GQSPI_IER_TXNOT_FULL_MASK); - if (!wait_for_completion_interruptible_timeout + if (!wait_for_completion_timeout (&xqspi->data_completion, msecs_to_jiffies(1000))) { err = -ETIMEDOUT; kfree(tmpbuf); @@ -1001,7 +1001,7 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem, GQSPI_IER_TXEMPTY_MASK | GQSPI_IER_GENFIFOEMPTY_MASK | GQSPI_IER_TXNOT_FULL_MASK); - if (!wait_for_completion_interruptible_timeout + if (!wait_for_completion_timeout (&xqspi->data_completion, msecs_to_jiffies(1000))) { err = -ETIMEDOUT; goto return_err; @@ -1076,7 +1076,7 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem, GQSPI_IER_RXEMPTY_MASK); } } - if (!wait_for_completion_interruptible_timeout + if (!wait_for_completion_timeout (&xqspi->data_completion, msecs_to_jiffies(1000))) err = -ETIMEDOUT; } From a0f65be6e880a14d3445b75e7dc03d7d015fc922 Mon Sep 17 00:00:00 2001 From: Quanyang Wang Date: Thu, 8 Apr 2021 12:02:21 +0800 Subject: [PATCH 074/113] spi: spi-zynqmp-gqspi: add mutex locking for exec_op The spi-mem framework has no locking to prevent ctlr->mem_ops->exec_op from concurrency. So add the locking to zynqmp_qspi_exec_op. Fixes: 1c26372e5aa9 ("spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework") Signed-off-by: Quanyang Wang Reviewed-by: Amit Kumar Mahapatra Link: https://lore.kernel.org/r/20210408040223.23134-3-quanyang.wang@windriver.com Signed-off-by: Mark Brown --- drivers/spi/spi-zynqmp-gqspi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index d49ab657555373..3b39461d58b3c5 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -173,6 +173,7 @@ struct zynqmp_qspi { u32 genfifoentry; enum mode_type mode; struct completion data_completion; + struct mutex op_lock; }; /** @@ -951,6 +952,7 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem, op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, op->dummy.buswidth, op->data.buswidth); + mutex_lock(&xqspi->op_lock); zynqmp_qspi_config_op(xqspi, mem->spi); zynqmp_qspi_chipselect(mem->spi, false); genfifoentry |= xqspi->genfifocs; @@ -1084,6 +1086,7 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem, return_err: zynqmp_qspi_chipselect(mem->spi, true); + mutex_unlock(&xqspi->op_lock); return err; } @@ -1156,6 +1159,8 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) goto clk_dis_pclk; } + mutex_init(&xqspi->op_lock); + pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); pm_runtime_set_active(&pdev->dev); From 8ad07d79bd56a531990a1a3f3f1c0eb19d2de806 Mon Sep 17 00:00:00 2001 From: Quanyang Wang Date: Thu, 8 Apr 2021 12:02:22 +0800 Subject: [PATCH 075/113] spi: spi-zynqmp-gqspi: transmit dummy circles by using the controller's internal functionality There is a data corruption issue that occurs in the reading operation (cmd:0x6c) when transmitting common data as dummy circles. The gqspi controller has the functionality to send dummy clock circles. When writing data with the fields [receive, transmit, data_xfer] = [0,0,1] to the Generic FIFO, and configuring the correct SPI mode, the controller will transmit dummy circles. So let's switch to hardware dummy cycles transfer to fix this issue. Fixes: 1c26372e5aa9 ("spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework") Signed-off-by: Quanyang Wang Reviewed-by: Amit Kumar Mahapatra Link: https://lore.kernel.org/r/20210408040223.23134-4-quanyang.wang@windriver.com Signed-off-by: Mark Brown --- drivers/spi/spi-zynqmp-gqspi.c | 40 +++++++++++++++------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index 3b39461d58b3c5..cf73a069b75944 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -521,7 +521,7 @@ static void zynqmp_qspi_filltxfifo(struct zynqmp_qspi *xqspi, int size) { u32 count = 0, intermediate; - while ((xqspi->bytes_to_transfer > 0) && (count < size)) { + while ((xqspi->bytes_to_transfer > 0) && (count < size) && (xqspi->txbuf)) { memcpy(&intermediate, xqspi->txbuf, 4); zynqmp_gqspi_write(xqspi, GQSPI_TXD_OFST, intermediate); @@ -580,7 +580,7 @@ static void zynqmp_qspi_fillgenfifo(struct zynqmp_qspi *xqspi, u8 nbits, genfifoentry |= GQSPI_GENFIFO_DATA_XFER; genfifoentry |= GQSPI_GENFIFO_TX; transfer_len = xqspi->bytes_to_transfer; - } else { + } else if (xqspi->rxbuf) { genfifoentry &= ~GQSPI_GENFIFO_TX; genfifoentry |= GQSPI_GENFIFO_DATA_XFER; genfifoentry |= GQSPI_GENFIFO_RX; @@ -588,6 +588,11 @@ static void zynqmp_qspi_fillgenfifo(struct zynqmp_qspi *xqspi, u8 nbits, transfer_len = xqspi->dma_rx_bytes; else transfer_len = xqspi->bytes_to_receive; + } else { + /* Sending dummy circles here */ + genfifoentry &= ~(GQSPI_GENFIFO_TX | GQSPI_GENFIFO_RX); + genfifoentry |= GQSPI_GENFIFO_DATA_XFER; + transfer_len = xqspi->bytes_to_transfer; } genfifoentry |= zynqmp_qspi_selectspimode(xqspi, nbits); xqspi->genfifoentry = genfifoentry; @@ -1011,32 +1016,23 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem, } if (op->dummy.nbytes) { - tmpbuf = kzalloc(op->dummy.nbytes, GFP_KERNEL | GFP_DMA); - if (!tmpbuf) - return -ENOMEM; - memset(tmpbuf, 0xff, op->dummy.nbytes); - reinit_completion(&xqspi->data_completion); - xqspi->txbuf = tmpbuf; + xqspi->txbuf = NULL; xqspi->rxbuf = NULL; - xqspi->bytes_to_transfer = op->dummy.nbytes; + /* + * xqspi->bytes_to_transfer here represents the dummy circles + * which need to be sent. + */ + xqspi->bytes_to_transfer = op->dummy.nbytes * 8 / op->dummy.buswidth; xqspi->bytes_to_receive = 0; - zynqmp_qspi_write_op(xqspi, op->dummy.buswidth, + /* + * Using op->data.buswidth instead of op->dummy.buswidth here because + * we need to use it to configure the correct SPI mode. + */ + zynqmp_qspi_write_op(xqspi, op->data.buswidth, genfifoentry); zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST) | GQSPI_CFG_START_GEN_FIFO_MASK); - zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST, - GQSPI_IER_TXEMPTY_MASK | - GQSPI_IER_GENFIFOEMPTY_MASK | - GQSPI_IER_TXNOT_FULL_MASK); - if (!wait_for_completion_interruptible_timeout - (&xqspi->data_completion, msecs_to_jiffies(1000))) { - err = -ETIMEDOUT; - kfree(tmpbuf); - goto return_err; - } - - kfree(tmpbuf); } if (op->data.nbytes) { From 41d310930084502433fcb3c4baf219e7424b7734 Mon Sep 17 00:00:00 2001 From: Quanyang Wang Date: Thu, 8 Apr 2021 12:02:23 +0800 Subject: [PATCH 076/113] spi: spi-zynqmp-gqspi: fix incorrect operating mode in zynqmp_qspi_read_op When starting a read operation, we should call zynqmp_qspi_setuprxdma first to set xqspi->mode according to xqspi->bytes_to_receive and to calculate correct xqspi->dma_rx_bytes. Then in the function zynqmp_qspi_fillgenfifo, generate the appropriate command with operating mode and bytes to transfer, and fill the GENFIFO with the command to perform the read operation. Calling zynqmp_qspi_fillgenfifo before zynqmp_qspi_setuprxdma will result in incorrect transfer length and operating mode. So change the calling order to fix this issue. Fixes: 1c26372e5aa9 ("spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework") Signed-off-by: Quanyang Wang Reviewed-by: Amit Kumar Mahapatra Link: https://lore.kernel.org/r/20210408040223.23134-5-quanyang.wang@windriver.com Signed-off-by: Mark Brown --- drivers/spi/spi-zynqmp-gqspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index cf73a069b75944..036d8ae41c0620 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -827,8 +827,8 @@ static void zynqmp_qspi_write_op(struct zynqmp_qspi *xqspi, u8 tx_nbits, static void zynqmp_qspi_read_op(struct zynqmp_qspi *xqspi, u8 rx_nbits, u32 genfifoentry) { - zynqmp_qspi_fillgenfifo(xqspi, rx_nbits, genfifoentry); zynqmp_qspi_setuprxdma(xqspi); + zynqmp_qspi_fillgenfifo(xqspi, rx_nbits, genfifoentry); } /** From 9b844b087124c1538d05f40fda8a4fec75af55be Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 9 Apr 2021 08:29:55 +0000 Subject: [PATCH 077/113] spi: dln2: Fix reference leak to master Call spi_master_get() holds the reference count to master device, thus we need an additional spi_master_put() call to reduce the reference count, otherwise we will leak a reference to master. This commit fix it by removing the unnecessary spi_master_get(). Reported-by: Hulk Robot Signed-off-by: Wei Yongjun Link: https://lore.kernel.org/r/20210409082955.2907950-1-weiyongjun1@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-dln2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-dln2.c b/drivers/spi/spi-dln2.c index 3902eadb892f91..3ff63ab82f4fbc 100644 --- a/drivers/spi/spi-dln2.c +++ b/drivers/spi/spi-dln2.c @@ -781,7 +781,7 @@ static int dln2_spi_probe(struct platform_device *pdev) static int dln2_spi_remove(struct platform_device *pdev) { - struct spi_master *master = spi_master_get(platform_get_drvdata(pdev)); + struct spi_master *master = platform_get_drvdata(pdev); struct dln2_spi *dln2 = spi_master_get_devdata(master); pm_runtime_disable(&pdev->dev); From 59ebbe40fb51e307032ae7f63b2749fad2d4635a Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Thu, 8 Apr 2021 08:55:07 +0800 Subject: [PATCH 078/113] spi: simplify devm_spi_register_controller Use devm_add_action_or_reset() instead of devres_alloc() and devres_add(), which works the same. This will simplify the code. There is no functional changes. Signed-off-by: Tian Tao Signed-off-by: Yicong Yang Link: https://lore.kernel.org/r/1617843307-53853-1-git-send-email-tiantao6@hisilicon.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 2fe3c3a508664e..b1419a3576e412 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2793,9 +2793,9 @@ int spi_register_controller(struct spi_controller *ctlr) } EXPORT_SYMBOL_GPL(spi_register_controller); -static void devm_spi_unregister(struct device *dev, void *res) +static void devm_spi_unregister(void *ctlr) { - spi_unregister_controller(*(struct spi_controller **)res); + spi_unregister_controller(ctlr); } /** @@ -2814,22 +2814,13 @@ static void devm_spi_unregister(struct device *dev, void *res) int devm_spi_register_controller(struct device *dev, struct spi_controller *ctlr) { - struct spi_controller **ptr; int ret; - ptr = devres_alloc(devm_spi_unregister, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return -ENOMEM; - ret = spi_register_controller(ctlr); - if (!ret) { - *ptr = ctlr; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } + if (ret) + return ret; - return ret; + return devm_add_action_or_reset(dev, devm_spi_unregister, ctlr); } EXPORT_SYMBOL_GPL(devm_spi_register_controller); From a03675497970a93fcf25d81d9d92a59c2d7377a7 Mon Sep 17 00:00:00 2001 From: Wang Li Date: Fri, 9 Apr 2021 09:54:30 +0000 Subject: [PATCH 079/113] spi: fsl-lpspi: Fix PM reference leak in lpspi_prepare_xfer_hardware() pm_runtime_get_sync will increment pm usage counter even it failed. Forgetting to putting operation will result in reference leak here. Fix it by replacing it with pm_runtime_resume_and_get to keep usage counter balanced. Fixes: 944c01a889d9 ("spi: lpspi: enable runtime pm for lpspi") Reported-by: Hulk Robot Signed-off-by: Wang Li Link: https://lore.kernel.org/r/20210409095430.29868-1-wangli74@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-lpspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index a2886ee44e4cb3..5d98611dd999d1 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -200,7 +200,7 @@ static int lpspi_prepare_xfer_hardware(struct spi_controller *controller) spi_controller_get_devdata(controller); int ret; - ret = pm_runtime_get_sync(fsl_lpspi->dev); + ret = pm_runtime_resume_and_get(fsl_lpspi->dev); if (ret < 0) { dev_err(fsl_lpspi->dev, "failed to enable clock\n"); return ret; From a23faea76d4cf5f75decb574491e66f9ecd707e7 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 9 Apr 2021 08:29:54 +0000 Subject: [PATCH 080/113] spi: omap-100k: Fix reference leak to master Call spi_master_get() holds the reference count to master device, thus we need an additional spi_master_put() call to reduce the reference count, otherwise we will leak a reference to master. This commit fix it by removing the unnecessary spi_master_get(). Reported-by: Hulk Robot Signed-off-by: Wei Yongjun Link: https://lore.kernel.org/r/20210409082954.2906933-1-weiyongjun1@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-omap-100k.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index 189fd2dda37bf9..7062f290225394 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c @@ -424,7 +424,7 @@ static int omap1_spi100k_probe(struct platform_device *pdev) static int omap1_spi100k_remove(struct platform_device *pdev) { - struct spi_master *master = spi_master_get(platform_get_drvdata(pdev)); + struct spi_master *master = platform_get_drvdata(pdev); struct omap1_spi100k *spi100k = spi_master_get_devdata(master); pm_runtime_disable(&pdev->dev); @@ -438,7 +438,7 @@ static int omap1_spi100k_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int omap1_spi100k_runtime_suspend(struct device *dev) { - struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); + struct spi_master *master = dev_get_drvdata(dev); struct omap1_spi100k *spi100k = spi_master_get_devdata(master); clk_disable_unprepare(spi100k->ick); @@ -449,7 +449,7 @@ static int omap1_spi100k_runtime_suspend(struct device *dev) static int omap1_spi100k_runtime_resume(struct device *dev) { - struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); + struct spi_master *master = dev_get_drvdata(dev); struct omap1_spi100k *spi100k = spi_master_get_devdata(master); int ret; From 4df2f5e1372e9eec8f9e1b4a3025b9be23487d36 Mon Sep 17 00:00:00 2001 From: Clark Wang Date: Thu, 8 Apr 2021 18:33:47 +0800 Subject: [PATCH 081/113] spi: imx: add a check for speed_hz before calculating the clock When some drivers use spi to send data, spi_transfer->speed_hz is not assigned. If spidev->max_speed_hz is not assigned as well, it will cause an error in configuring the clock. Add a check for these two values before configuring the clock. An error will be returned when they are not assigned. Signed-off-by: Clark Wang Link: https://lore.kernel.org/r/20210408103347.244313-2-xiaoning.wang@nxp.com Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index cf5519227dbdd4..64e8f0828e8560 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -66,8 +66,7 @@ struct spi_imx_data; struct spi_imx_devtype_data { void (*intctrl)(struct spi_imx_data *, int); int (*prepare_message)(struct spi_imx_data *, struct spi_message *); - int (*prepare_transfer)(struct spi_imx_data *, struct spi_device *, - struct spi_transfer *); + int (*prepare_transfer)(struct spi_imx_data *, struct spi_device *); void (*trigger)(struct spi_imx_data *); int (*rx_available)(struct spi_imx_data *); void (*reset)(struct spi_imx_data *); @@ -572,11 +571,10 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, } static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx, - struct spi_device *spi, - struct spi_transfer *t) + struct spi_device *spi) { u32 ctrl = readl(spi_imx->base + MX51_ECSPI_CTRL); - u32 clk = t->speed_hz, delay; + u32 clk, delay; /* Clear BL field and set the right value */ ctrl &= ~MX51_ECSPI_CTRL_BL_MASK; @@ -590,7 +588,7 @@ static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx, /* set clock speed */ ctrl &= ~(0xf << MX51_ECSPI_CTRL_POSTDIV_OFFSET | 0xf << MX51_ECSPI_CTRL_PREDIV_OFFSET); - ctrl |= mx51_ecspi_clkdiv(spi_imx, t->speed_hz, &clk); + ctrl |= mx51_ecspi_clkdiv(spi_imx, spi_imx->spi_bus_clk, &clk); spi_imx->spi_bus_clk = clk; if (spi_imx->usedma) @@ -702,13 +700,12 @@ static int mx31_prepare_message(struct spi_imx_data *spi_imx, } static int mx31_prepare_transfer(struct spi_imx_data *spi_imx, - struct spi_device *spi, - struct spi_transfer *t) + struct spi_device *spi) { unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER; unsigned int clk; - reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, t->speed_hz, &clk) << + reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, spi_imx->spi_bus_clk, &clk) << MX31_CSPICTRL_DR_SHIFT; spi_imx->spi_bus_clk = clk; @@ -807,14 +804,13 @@ static int mx21_prepare_message(struct spi_imx_data *spi_imx, } static int mx21_prepare_transfer(struct spi_imx_data *spi_imx, - struct spi_device *spi, - struct spi_transfer *t) + struct spi_device *spi) { unsigned int reg = MX21_CSPICTRL_ENABLE | MX21_CSPICTRL_MASTER; unsigned int max = is_imx27_cspi(spi_imx) ? 16 : 18; unsigned int clk; - reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, t->speed_hz, max, &clk) + reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, spi_imx->spi_bus_clk, max, &clk) << MX21_CSPICTRL_DR_SHIFT; spi_imx->spi_bus_clk = clk; @@ -883,13 +879,12 @@ static int mx1_prepare_message(struct spi_imx_data *spi_imx, } static int mx1_prepare_transfer(struct spi_imx_data *spi_imx, - struct spi_device *spi, - struct spi_transfer *t) + struct spi_device *spi) { unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER; unsigned int clk; - reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, t->speed_hz, &clk) << + reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, spi_imx->spi_bus_clk, &clk) << MX1_CSPICTRL_DR_SHIFT; spi_imx->spi_bus_clk = clk; @@ -1168,6 +1163,16 @@ static int spi_imx_setupxfer(struct spi_device *spi, if (!t) return 0; + if (!t->speed_hz) { + if (!spi->max_speed_hz) { + dev_err(&spi->dev, "no speed_hz provided!\n"); + return -EINVAL; + } + dev_dbg(&spi->dev, "using spi->max_speed_hz!\n"); + spi_imx->spi_bus_clk = spi->max_speed_hz; + } else + spi_imx->spi_bus_clk = t->speed_hz; + spi_imx->bits_per_word = t->bits_per_word; /* @@ -1209,7 +1214,7 @@ static int spi_imx_setupxfer(struct spi_device *spi, spi_imx->slave_burst = t->len; } - spi_imx->devtype_data->prepare_transfer(spi_imx, spi, t); + spi_imx->devtype_data->prepare_transfer(spi_imx, spi); return 0; } From e980048263ba72dcdbbf45d59e84c02001340f75 Mon Sep 17 00:00:00 2001 From: Muhammad Usama Anjum Date: Fri, 9 Apr 2021 00:57:18 +0500 Subject: [PATCH 082/113] spi: orion: set devdata properly as it is being used later If device_get_match_data returns NULL, devdata isn't being updated properly. It is being used later in the function. Both devdata and spi->devdata should be updated to avoid NULL pointer dereference. Addresses-Coverity: ("NULL pointer dereference") Fixes: 0e6521f13c2 ("spi: orion: Use device_get_match_data() helper") Signed-off-by: Muhammad Usama Anjum Link: https://lore.kernel.org/r/20210408195718.GA3075166@LEGION Signed-off-by: Mark Brown --- drivers/spi/spi-orion.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index d02c5c9def20ce..34b31aba398171 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -676,7 +676,8 @@ static int orion_spi_probe(struct platform_device *pdev) spi->dev = &pdev->dev; devdata = device_get_match_data(&pdev->dev); - spi->devdata = devdata ? devdata : &orion_spi_dev_data; + devdata = devdata ? devdata : &orion_spi_dev_data; + spi->devdata = devdata; spi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(spi->clk)) { From cec77e0a249892ceb10061bf17b63f9fb111d870 Mon Sep 17 00:00:00 2001 From: Wang Li Date: Fri, 9 Apr 2021 09:54:58 +0000 Subject: [PATCH 083/113] spi: qup: fix PM reference leak in spi_qup_remove() pm_runtime_get_sync will increment pm usage counter even it failed. Forgetting to putting operation will result in reference leak here. Fix it by replacing it with pm_runtime_resume_and_get to keep usage counter balanced. Reported-by: Hulk Robot Signed-off-by: Wang Li Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20210409095458.29921-1-wangli74@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-qup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index 8dcb2e70735c91..d39dec6d1c91e8 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -1263,7 +1263,7 @@ static int spi_qup_remove(struct platform_device *pdev) struct spi_qup *controller = spi_master_get_devdata(master); int ret; - ret = pm_runtime_get_sync(&pdev->dev); + ret = pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) return ret; From 30700a057ce84e6f18f4cc3627570f8b2ae3c17f Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Wed, 31 Mar 2021 08:58:39 +0800 Subject: [PATCH 084/113] spi: davinci: Use device_get_match_data() helper Use the device_get_match_data() helper instead of open coding. Signed-off-by: Tian Tao Suggested-by: Fabio Estevam Link: https://lore.kernel.org/r/1617152319-17701-1-git-send-email-tiantao6@hisilicon.com Signed-off-by: Mark Brown --- drivers/spi/spi-davinci.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 7453a1dbbc0614..e114e6fe5ea5b4 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -817,18 +817,13 @@ static int spi_davinci_get_pdata(struct platform_device *pdev, struct davinci_spi *dspi) { struct device_node *node = pdev->dev.of_node; - struct davinci_spi_of_data *spi_data; + const struct davinci_spi_of_data *spi_data; struct davinci_spi_platform_data *pdata; unsigned int num_cs, intr_line = 0; - const struct of_device_id *match; pdata = &dspi->pdata; - match = of_match_device(davinci_spi_of_match, &pdev->dev); - if (!match) - return -ENODEV; - - spi_data = (struct davinci_spi_of_data *)match->data; + spi_data = device_get_match_data(&pdev->dev); pdata->version = spi_data->version; pdata->prescaler_limit = spi_data->prescaler_limit; From 4c84e42d29afa3dce201a4db747db2a5ba404604 Mon Sep 17 00:00:00 2001 From: Yicong Yang Date: Mon, 12 Apr 2021 19:58:27 +0800 Subject: [PATCH 085/113] spi: hisi-sfc-v3xx: fix potential irq race condition We mask the irq when the command completion is timeout. This won't stop the already running irq handler. Use sychronize_irq() after we mask the irq, to make sure there is no running handler. Acked-by: John Garry Signed-off-by: Yicong Yang Link: https://lore.kernel.org/r/1618228708-37949-2-git-send-email-yangyicong@hisilicon.com Signed-off-by: Mark Brown --- drivers/spi/spi-hisi-sfc-v3xx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-hisi-sfc-v3xx.c b/drivers/spi/spi-hisi-sfc-v3xx.c index 385eb7bba05a5a..0d9e10302b664d 100644 --- a/drivers/spi/spi-hisi-sfc-v3xx.c +++ b/drivers/spi/spi-hisi-sfc-v3xx.c @@ -342,6 +342,7 @@ static int hisi_sfc_v3xx_generic_exec_op(struct hisi_sfc_v3xx_host *host, ret = 0; hisi_sfc_v3xx_disable_int(host); + synchronize_irq(host->irq); host->completion = NULL; } else { ret = hisi_sfc_v3xx_wait_cmd_idle(host); From 4a46f88681ca514f9cb33b39312d0ec4e2ec84da Mon Sep 17 00:00:00 2001 From: Yicong Yang Date: Mon, 12 Apr 2021 19:58:28 +0800 Subject: [PATCH 086/113] spi: hisi-sfc-v3xx: drop unnecessary ACPI_PTR and related ifendif protection We use ACPI_PTR() and related ifendif protection for the id table. This is unnecessary as the struct acpi_device_id is defined in mod_devicetable.h and doesn't rely on ACPI. The driver doesn't use any ACPI apis, so it can be compiled in the ACPI=n case with no warnings. So remove the ACPI_PTR and related ifendif protection, also replace the header acpi.h with mod_devicetable.h. Acked-by: John Garry Signed-off-by: Yicong Yang Link: https://lore.kernel.org/r/1618228708-37949-3-git-send-email-yangyicong@hisilicon.com Signed-off-by: Mark Brown --- drivers/spi/spi-hisi-sfc-v3xx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-hisi-sfc-v3xx.c b/drivers/spi/spi-hisi-sfc-v3xx.c index 0d9e10302b664d..d3a23b1c2a4c54 100644 --- a/drivers/spi/spi-hisi-sfc-v3xx.c +++ b/drivers/spi/spi-hisi-sfc-v3xx.c @@ -5,13 +5,13 @@ // Copyright (c) 2019 HiSilicon Technologies Co., Ltd. // Author: John Garry -#include #include #include #include #include #include #include +#include #include #include #include @@ -508,18 +508,16 @@ static int hisi_sfc_v3xx_probe(struct platform_device *pdev) return ret; } -#if IS_ENABLED(CONFIG_ACPI) static const struct acpi_device_id hisi_sfc_v3xx_acpi_ids[] = { {"HISI0341", 0}, {} }; MODULE_DEVICE_TABLE(acpi, hisi_sfc_v3xx_acpi_ids); -#endif static struct platform_driver hisi_sfc_v3xx_spi_driver = { .driver = { .name = "hisi-sfc-v3xx", - .acpi_match_table = ACPI_PTR(hisi_sfc_v3xx_acpi_ids), + .acpi_match_table = hisi_sfc_v3xx_acpi_ids, }, .probe = hisi_sfc_v3xx_probe, }; From 6043357263fbe2df0bf0736d971ad5dce7d19dc1 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 12 Apr 2021 16:00:25 +0000 Subject: [PATCH 087/113] spi: spi-zynqmp-gqspi: Fix missing unlock on error in zynqmp_qspi_exec_op() Add the missing unlock before return from function zynqmp_qspi_exec_op() in the error handling case. Fixes: a0f65be6e880 ("spi: spi-zynqmp-gqspi: add mutex locking for exec_op") Reported-by: Hulk Robot Signed-off-by: Wei Yongjun Link: https://lore.kernel.org/r/20210412160025.194171-1-weiyongjun1@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi-zynqmp-gqspi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index 036d8ae41c0620..408e348382c5c1 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -965,8 +965,10 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem, if (op->cmd.opcode) { tmpbuf = kzalloc(op->cmd.nbytes, GFP_KERNEL | GFP_DMA); - if (!tmpbuf) + if (!tmpbuf) { + mutex_unlock(&xqspi->op_lock); return -ENOMEM; + } tmpbuf[0] = op->cmd.opcode; reinit_completion(&xqspi->data_completion); xqspi->txbuf = tmpbuf; From 8c4ffe4d023d7a3153c1d3d1084d98d17bf684b9 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 15 Apr 2021 16:59:17 +0300 Subject: [PATCH 088/113] spi: pxa2xx: Add support for Intel Alder Lake PCH-M Add support for LPSS SPI on Intel Alder Lake PCH-M. Signed-off-by: Jarkko Nikula Link: https://lore.kernel.org/r/20210415135917.54144-1-jarkko.nikula@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 0cc767283674b2..f2fa2a1f92c42d 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1496,6 +1496,10 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = { { PCI_VDEVICE(INTEL, 0x51aa), LPSS_CNL_SSP }, { PCI_VDEVICE(INTEL, 0x51ab), LPSS_CNL_SSP }, { PCI_VDEVICE(INTEL, 0x51fb), LPSS_CNL_SSP }, + /* ADL-M */ + { PCI_VDEVICE(INTEL, 0x54aa), LPSS_CNL_SSP }, + { PCI_VDEVICE(INTEL, 0x54ab), LPSS_CNL_SSP }, + { PCI_VDEVICE(INTEL, 0x54fb), LPSS_CNL_SSP }, /* APL */ { PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP }, From 609a2f9529d3d3e627776614b6cff34b21f64144 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 14 Apr 2021 22:33:41 +0200 Subject: [PATCH 089/113] spi: s3c64xx: simplify getting of_device_id match data Use of_device_get_match_data() to make the code slightly smaller and to remove the of_device_id table forward declaration. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Sylwester Nawrocki Link: https://lore.kernel.org/r/20210414203343.203119-1-krzysztof.kozlowski@canonical.com Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index dfa7c91e13aa58..c6d7641ea34234 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -1048,17 +1049,12 @@ static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev) } #endif -static const struct of_device_id s3c64xx_spi_dt_match[]; - static inline struct s3c64xx_spi_port_config *s3c64xx_spi_get_port_config( struct platform_device *pdev) { #ifdef CONFIG_OF - if (pdev->dev.of_node) { - const struct of_device_id *match; - match = of_match_node(s3c64xx_spi_dt_match, pdev->dev.of_node); - return (struct s3c64xx_spi_port_config *)match->data; - } + if (pdev->dev.of_node) + return (struct s3c64xx_spi_port_config *)of_device_get_match_data(&pdev->dev); #endif return (struct s3c64xx_spi_port_config *) platform_get_device_id(pdev)->driver_data; From 7d712f799a938b37d24359ea836f58866be5e0bb Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 14 Apr 2021 22:33:42 +0200 Subject: [PATCH 090/113] spi: s3c64xx: correct kerneldoc of s3c64xx_spi_port_config Correct the name of s3c64xx_spi_port_config structure in kerneldoc: drivers/spi/spi-s3c64xx.c:154: warning: expecting prototype for struct s3c64xx_spi_info. Prototype was for struct s3c64xx_spi_port_config instead Signed-off-by: Krzysztof Kozlowski Reviewed-by: Sylwester Nawrocki Link: https://lore.kernel.org/r/20210414203343.203119-2-krzysztof.kozlowski@canonical.com Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index c6d7641ea34234..eac3c300f806a2 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -128,7 +128,7 @@ struct s3c64xx_spi_dma_data { }; /** - * struct s3c64xx_spi_info - SPI Controller hardware info + * struct s3c64xx_spi_port_config - SPI Controller hardware info * @fifo_lvl_mask: Bit-mask for {TX|RX}_FIFO_LVL bits in SPI_STATUS register. * @rx_lvl_offset: Bit offset of RX_FIFO_LVL bits in SPI_STATUS regiter. * @tx_st_done: Bit offset of TX_DONE bit in SPI_STATUS regiter. From d6371415517700ae225dd1aaa8a35a86a659ada6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 14 Apr 2021 22:33:43 +0200 Subject: [PATCH 091/113] spi: s3c64xx: constify driver/match data The match data (struct s3c64xx_spi_port_config) stored in of_device_id and platform_device_id tables is not modified by the driver and can be handled entirely in a const-way to increase the code safety. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Sylwester Nawrocki Link: https://lore.kernel.org/r/20210414203343.203119-3-krzysztof.kozlowski@canonical.com Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index eac3c300f806a2..8755cd85e83ceb 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -190,7 +190,7 @@ struct s3c64xx_spi_driver_data { unsigned cur_speed; struct s3c64xx_spi_dma_data rx_dma; struct s3c64xx_spi_dma_data tx_dma; - struct s3c64xx_spi_port_config *port_conf; + const struct s3c64xx_spi_port_config *port_conf; unsigned int port_id; }; @@ -1049,15 +1049,14 @@ static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev) } #endif -static inline struct s3c64xx_spi_port_config *s3c64xx_spi_get_port_config( +static inline const struct s3c64xx_spi_port_config *s3c64xx_spi_get_port_config( struct platform_device *pdev) { #ifdef CONFIG_OF if (pdev->dev.of_node) - return (struct s3c64xx_spi_port_config *)of_device_get_match_data(&pdev->dev); + return of_device_get_match_data(&pdev->dev); #endif - return (struct s3c64xx_spi_port_config *) - platform_get_device_id(pdev)->driver_data; + return (const struct s3c64xx_spi_port_config *)platform_get_device_id(pdev)->driver_data; } static int s3c64xx_spi_probe(struct platform_device *pdev) @@ -1395,27 +1394,27 @@ static const struct dev_pm_ops s3c64xx_spi_pm = { s3c64xx_spi_runtime_resume, NULL) }; -static struct s3c64xx_spi_port_config s3c2443_spi_port_config = { +static const struct s3c64xx_spi_port_config s3c2443_spi_port_config = { .fifo_lvl_mask = { 0x7f }, .rx_lvl_offset = 13, .tx_st_done = 21, .high_speed = true, }; -static struct s3c64xx_spi_port_config s3c6410_spi_port_config = { +static const struct s3c64xx_spi_port_config s3c6410_spi_port_config = { .fifo_lvl_mask = { 0x7f, 0x7F }, .rx_lvl_offset = 13, .tx_st_done = 21, }; -static struct s3c64xx_spi_port_config s5pv210_spi_port_config = { +static const struct s3c64xx_spi_port_config s5pv210_spi_port_config = { .fifo_lvl_mask = { 0x1ff, 0x7F }, .rx_lvl_offset = 15, .tx_st_done = 25, .high_speed = true, }; -static struct s3c64xx_spi_port_config exynos4_spi_port_config = { +static const struct s3c64xx_spi_port_config exynos4_spi_port_config = { .fifo_lvl_mask = { 0x1ff, 0x7F, 0x7F }, .rx_lvl_offset = 15, .tx_st_done = 25, @@ -1424,7 +1423,7 @@ static struct s3c64xx_spi_port_config exynos4_spi_port_config = { .quirks = S3C64XX_SPI_QUIRK_CS_AUTO, }; -static struct s3c64xx_spi_port_config exynos7_spi_port_config = { +static const struct s3c64xx_spi_port_config exynos7_spi_port_config = { .fifo_lvl_mask = { 0x1ff, 0x7F, 0x7F, 0x7F, 0x7F, 0x1ff}, .rx_lvl_offset = 15, .tx_st_done = 25, @@ -1433,7 +1432,7 @@ static struct s3c64xx_spi_port_config exynos7_spi_port_config = { .quirks = S3C64XX_SPI_QUIRK_CS_AUTO, }; -static struct s3c64xx_spi_port_config exynos5433_spi_port_config = { +static const struct s3c64xx_spi_port_config exynos5433_spi_port_config = { .fifo_lvl_mask = { 0x1ff, 0x7f, 0x7f, 0x7f, 0x7f, 0x1ff}, .rx_lvl_offset = 15, .tx_st_done = 25, From 58eaa7b2d07d3c25e1068b0bf42ca7e7464f4bca Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Thu, 15 Apr 2021 15:46:44 +0800 Subject: [PATCH 092/113] spi: spi-zynqmp-gqspi: Fix runtime PM imbalance in zynqmp_qspi_probe There is a PM usage counter decrement after zynqmp_qspi_init_hw() without any refcount increment, which leads to refcount leak.Add a refcount increment to balance the refcount. Also set auto_runtime_pm to resume suspended spi controller. Fixes: 9e3a000362aec ("spi: zynqmp: Add pm runtime support") Signed-off-by: Dinghao Liu Tested-by: Quanyang Wang Link: https://lore.kernel.org/r/20210415074644.24646-1-dinghao.liu@zju.edu.cn Signed-off-by: Mark Brown --- drivers/spi/spi-zynqmp-gqspi.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index 408e348382c5c1..32e53f379e9b15 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -1163,11 +1163,16 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); + + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to pm_runtime_get_sync: %d\n", ret); + goto clk_dis_all; + } + /* QSPI controller initializations */ zynqmp_qspi_init_hw(xqspi); - pm_runtime_mark_last_busy(&pdev->dev); - pm_runtime_put_autosuspend(&pdev->dev); xqspi->irq = platform_get_irq(pdev, 0); if (xqspi->irq <= 0) { ret = -ENXIO; @@ -1190,6 +1195,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_DUAL | SPI_TX_QUAD; ctlr->dev.of_node = np; + ctlr->auto_runtime_pm = true; ret = devm_spi_register_controller(&pdev->dev, ctlr); if (ret) { @@ -1197,9 +1203,13 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) goto clk_dis_all; } + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); + return 0; clk_dis_all: + pm_runtime_put_sync(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_runtime_disable(&pdev->dev); clk_disable_unprepare(xqspi->refclk); From c6bdae08012b2ca3e94f3a41ef4ca8cfe7c9ab6f Mon Sep 17 00:00:00 2001 From: Quanyang Wang Date: Fri, 16 Apr 2021 08:46:48 +0800 Subject: [PATCH 093/113] spi: spi-zynqmp-gqspi: fix clk_enable/disable imbalance issue The clks "pclk" and "ref_clk" are enabled twice during the probe. The first time is in the function zynqmp_qspi_probe and the second time is in zynqmp_qspi_setup_op which is called by devm_spi_register_controller. Then calling zynqmp_qspi_remove (rmmod this module) to disable these clks will trigger a warning as below: [ 309.124604] Unpreparing enabled qspi_ref [ 309.128641] WARNING: CPU: 1 PID: 537 at drivers/clk/clk.c:824 clk_core_unprepare+0x108/0x110 Since pm_runtime works now, clks can be enabled/disabled by calling zynqmp_runtime_suspend/resume. So we don't need to enable these clks explicitly in zynqmp_qspi_setup_op. Remove them to fix this issue. And remove clk enabling/disabling in zynqmp_qspi_resume because there is no spi transfer operation so enabling ref_clk is redundant meanwhile pclk is not disabled for it is shared with other peripherals. Furthermore replace clk_enable/disable with clk_prepare_enable and clk_disable_unprepare in runtime_suspend/resume functions. Fixes: 1c26372e5aa9 ("spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework") Signed-off-by: Quanyang Wang Link: https://lore.kernel.org/r/20210416004652.2975446-2-quanyang.wang@windriver.com Signed-off-by: Mark Brown --- drivers/spi/spi-zynqmp-gqspi.c | 47 ++++++---------------------------- 1 file changed, 8 insertions(+), 39 deletions(-) diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index 32e53f379e9b15..f9056f0a480cef 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -487,24 +487,10 @@ static int zynqmp_qspi_setup_op(struct spi_device *qspi) { struct spi_controller *ctlr = qspi->master; struct zynqmp_qspi *xqspi = spi_controller_get_devdata(ctlr); - struct device *dev = &ctlr->dev; - int ret; if (ctlr->busy) return -EBUSY; - ret = clk_enable(xqspi->refclk); - if (ret) { - dev_err(dev, "Cannot enable device clock.\n"); - return ret; - } - - ret = clk_enable(xqspi->pclk); - if (ret) { - dev_err(dev, "Cannot enable APB clock.\n"); - clk_disable(xqspi->refclk); - return ret; - } zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, GQSPI_EN_MASK); return 0; @@ -863,26 +849,9 @@ static int __maybe_unused zynqmp_qspi_suspend(struct device *dev) static int __maybe_unused zynqmp_qspi_resume(struct device *dev) { struct spi_controller *ctlr = dev_get_drvdata(dev); - struct zynqmp_qspi *xqspi = spi_controller_get_devdata(ctlr); - int ret = 0; - - ret = clk_enable(xqspi->pclk); - if (ret) { - dev_err(dev, "Cannot enable APB clock.\n"); - return ret; - } - - ret = clk_enable(xqspi->refclk); - if (ret) { - dev_err(dev, "Cannot enable device clock.\n"); - clk_disable(xqspi->pclk); - return ret; - } spi_controller_resume(ctlr); - clk_disable(xqspi->refclk); - clk_disable(xqspi->pclk); return 0; } @@ -898,8 +867,8 @@ static int __maybe_unused zynqmp_runtime_suspend(struct device *dev) { struct zynqmp_qspi *xqspi = (struct zynqmp_qspi *)dev_get_drvdata(dev); - clk_disable(xqspi->refclk); - clk_disable(xqspi->pclk); + clk_disable_unprepare(xqspi->refclk); + clk_disable_unprepare(xqspi->pclk); return 0; } @@ -917,16 +886,16 @@ static int __maybe_unused zynqmp_runtime_resume(struct device *dev) struct zynqmp_qspi *xqspi = (struct zynqmp_qspi *)dev_get_drvdata(dev); int ret; - ret = clk_enable(xqspi->pclk); + ret = clk_prepare_enable(xqspi->pclk); if (ret) { dev_err(dev, "Cannot enable APB clock.\n"); return ret; } - ret = clk_enable(xqspi->refclk); + ret = clk_prepare_enable(xqspi->refclk); if (ret) { dev_err(dev, "Cannot enable device clock.\n"); - clk_disable(xqspi->pclk); + clk_disable_unprepare(xqspi->pclk); return ret; } @@ -1136,13 +1105,11 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) goto remove_master; } - init_completion(&xqspi->data_completion); - xqspi->refclk = devm_clk_get(&pdev->dev, "ref_clk"); if (IS_ERR(xqspi->refclk)) { dev_err(dev, "ref_clk clock not found.\n"); ret = PTR_ERR(xqspi->refclk); - goto clk_dis_pclk; + goto remove_master; } ret = clk_prepare_enable(xqspi->pclk); @@ -1157,6 +1124,8 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) goto clk_dis_pclk; } + init_completion(&xqspi->data_completion); + mutex_init(&xqspi->op_lock); pm_runtime_use_autosuspend(&pdev->dev); From 799f923f0a66a9c99f0a3eaa078b306db7a8b33a Mon Sep 17 00:00:00 2001 From: Quanyang Wang Date: Fri, 16 Apr 2021 08:46:49 +0800 Subject: [PATCH 094/113] spi: spi-zynqmp-gqspi: fix hang issue when suspend/resume After calling platform_set_drvdata(pdev, xqspi) in probe, the return value of dev_get_drvdata(dev) is a pointer to struct zynqmp_qspi but not struct spi_controller. A wrong structure type passing to the functions spi_controller_suspend/resume will hang the system. And we should check the return value of spi_controller_suspend, if an error is returned, return it to PM subsystem to stop suspend. Also, GQSPI_EN_MASK should be written to GQSPI_EN_OFST to enable the spi controller in zynqmp_qspi_resume since it was disabled in zynqmp_qspi_suspend before. Fixes: 1c26372e5aa9 ("spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework") Signed-off-by: Quanyang Wang Link: https://lore.kernel.org/r/20210416004652.2975446-3-quanyang.wang@windriver.com Signed-off-by: Mark Brown --- drivers/spi/spi-zynqmp-gqspi.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index f9056f0a480cef..1146359528b9f5 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -157,6 +157,7 @@ enum mode_type {GQSPI_MODE_IO, GQSPI_MODE_DMA}; * @data_completion: completion structure */ struct zynqmp_qspi { + struct spi_controller *ctlr; void __iomem *regs; struct clk *refclk; struct clk *pclk; @@ -827,10 +828,13 @@ static void zynqmp_qspi_read_op(struct zynqmp_qspi *xqspi, u8 rx_nbits, */ static int __maybe_unused zynqmp_qspi_suspend(struct device *dev) { - struct spi_controller *ctlr = dev_get_drvdata(dev); - struct zynqmp_qspi *xqspi = spi_controller_get_devdata(ctlr); + struct zynqmp_qspi *xqspi = dev_get_drvdata(dev); + struct spi_controller *ctlr = xqspi->ctlr; + int ret; - spi_controller_suspend(ctlr); + ret = spi_controller_suspend(ctlr); + if (ret) + return ret; zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, 0x0); @@ -848,7 +852,10 @@ static int __maybe_unused zynqmp_qspi_suspend(struct device *dev) */ static int __maybe_unused zynqmp_qspi_resume(struct device *dev) { - struct spi_controller *ctlr = dev_get_drvdata(dev); + struct zynqmp_qspi *xqspi = dev_get_drvdata(dev); + struct spi_controller *ctlr = xqspi->ctlr; + + zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, GQSPI_EN_MASK); spi_controller_resume(ctlr); @@ -865,7 +872,7 @@ static int __maybe_unused zynqmp_qspi_resume(struct device *dev) */ static int __maybe_unused zynqmp_runtime_suspend(struct device *dev) { - struct zynqmp_qspi *xqspi = (struct zynqmp_qspi *)dev_get_drvdata(dev); + struct zynqmp_qspi *xqspi = dev_get_drvdata(dev); clk_disable_unprepare(xqspi->refclk); clk_disable_unprepare(xqspi->pclk); @@ -883,7 +890,7 @@ static int __maybe_unused zynqmp_runtime_suspend(struct device *dev) */ static int __maybe_unused zynqmp_runtime_resume(struct device *dev) { - struct zynqmp_qspi *xqspi = (struct zynqmp_qspi *)dev_get_drvdata(dev); + struct zynqmp_qspi *xqspi = dev_get_drvdata(dev); int ret; ret = clk_prepare_enable(xqspi->pclk); @@ -1090,6 +1097,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) xqspi = spi_controller_get_devdata(ctlr); xqspi->dev = dev; + xqspi->ctlr = ctlr; platform_set_drvdata(pdev, xqspi); xqspi->regs = devm_platform_ioremap_resource(pdev, 0); From 2530b3df4326023a171977ab46fdfeac0340f5b2 Mon Sep 17 00:00:00 2001 From: Amit Kumar Mahapatra Date: Fri, 16 Apr 2021 08:46:50 +0800 Subject: [PATCH 095/113] spi: spi-zynqmp-gqspi: Resolved slab-out-of-bounds bug During a transfer the driver filled the fifo with 4bytes, even if the data that needs to be transfer is less that 4bytes. This resulted in slab-out-of-bounds bug in KernelAddressSanitizer. This patch resolves slab-out-of-bounds bug by filling the fifo with the number of bytes that needs to transferred. Signed-off-by: Amit Kumar Mahapatra Link: https://lore.kernel.org/r/20210416004652.2975446-4-quanyang.wang@windriver.com Signed-off-by: Mark Brown --- drivers/spi/spi-zynqmp-gqspi.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index 1146359528b9f5..2e2607b5dee9dc 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -509,17 +509,19 @@ static void zynqmp_qspi_filltxfifo(struct zynqmp_qspi *xqspi, int size) u32 count = 0, intermediate; while ((xqspi->bytes_to_transfer > 0) && (count < size) && (xqspi->txbuf)) { - memcpy(&intermediate, xqspi->txbuf, 4); - zynqmp_gqspi_write(xqspi, GQSPI_TXD_OFST, intermediate); - if (xqspi->bytes_to_transfer >= 4) { + memcpy(&intermediate, xqspi->txbuf, 4); xqspi->txbuf += 4; xqspi->bytes_to_transfer -= 4; + count += 4; } else { + memcpy(&intermediate, xqspi->txbuf, + xqspi->bytes_to_transfer); xqspi->txbuf += xqspi->bytes_to_transfer; xqspi->bytes_to_transfer = 0; + count += xqspi->bytes_to_transfer; } - count++; + zynqmp_gqspi_write(xqspi, GQSPI_TXD_OFST, intermediate); } } From a2c5bedb2d55dd27c642c7b9fb6886d7ad7bdb58 Mon Sep 17 00:00:00 2001 From: Quanyang Wang Date: Fri, 16 Apr 2021 08:46:51 +0800 Subject: [PATCH 096/113] spi: spi-zynqmp-gqspi: fix use-after-free in zynqmp_qspi_exec_op When handling op->addr, it is using the buffer "tmpbuf" which has been freed. This will trigger a use-after-free KASAN warning. Let's use temporary variables to store op->addr.val and op->cmd.opcode to fix this issue. Fixes: 1c26372e5aa9 ("spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework") Signed-off-by: Quanyang Wang Link: https://lore.kernel.org/r/20210416004652.2975446-5-quanyang.wang@windriver.com Signed-off-by: Mark Brown --- drivers/spi/spi-zynqmp-gqspi.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index 2e2607b5dee9dc..419bc1e6358b7a 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -928,8 +928,9 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem, struct zynqmp_qspi *xqspi = spi_controller_get_devdata (mem->spi->master); int err = 0, i; - u8 *tmpbuf; u32 genfifoentry = 0; + u16 opcode = op->cmd.opcode; + u64 opaddr; dev_dbg(xqspi->dev, "cmd:%#x mode:%d.%d.%d.%d\n", op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, @@ -942,14 +943,8 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem, genfifoentry |= xqspi->genfifobus; if (op->cmd.opcode) { - tmpbuf = kzalloc(op->cmd.nbytes, GFP_KERNEL | GFP_DMA); - if (!tmpbuf) { - mutex_unlock(&xqspi->op_lock); - return -ENOMEM; - } - tmpbuf[0] = op->cmd.opcode; reinit_completion(&xqspi->data_completion); - xqspi->txbuf = tmpbuf; + xqspi->txbuf = &opcode; xqspi->rxbuf = NULL; xqspi->bytes_to_transfer = op->cmd.nbytes; xqspi->bytes_to_receive = 0; @@ -963,13 +958,12 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem, if (!wait_for_completion_timeout (&xqspi->data_completion, msecs_to_jiffies(1000))) { err = -ETIMEDOUT; - kfree(tmpbuf); goto return_err; } - kfree(tmpbuf); } if (op->addr.nbytes) { + xqspi->txbuf = &opaddr; for (i = 0; i < op->addr.nbytes; i++) { *(((u8 *)xqspi->txbuf) + i) = op->addr.val >> (8 * (op->addr.nbytes - i - 1)); From 126bdb606fd2802454e6048caef1be3e25dd121e Mon Sep 17 00:00:00 2001 From: Quanyang Wang Date: Fri, 16 Apr 2021 08:46:52 +0800 Subject: [PATCH 097/113] spi: spi-zynqmp-gqspi: return -ENOMEM if dma_map_single fails The spi controller supports 44-bit address space on AXI in DMA mode, so set dma_addr_t width to 44-bit to avoid using a swiotlb mapping. In addition, if dma_map_single fails, it should return immediately instead of continuing doing the DMA operation which bases on invalid address. This fixes the following crash which occurs in reading a big block from flash: [ 123.633577] zynqmp-qspi ff0f0000.spi: swiotlb buffer is full (sz: 4194304 bytes), total 32768 (slots), used 0 (slots) [ 123.644230] zynqmp-qspi ff0f0000.spi: ERR:rxdma:memory not mapped [ 123.784625] Unable to handle kernel paging request at virtual address 00000000003fffc0 [ 123.792536] Mem abort info: [ 123.795313] ESR = 0x96000145 [ 123.798351] EC = 0x25: DABT (current EL), IL = 32 bits [ 123.803655] SET = 0, FnV = 0 [ 123.806693] EA = 0, S1PTW = 0 [ 123.809818] Data abort info: [ 123.812683] ISV = 0, ISS = 0x00000145 [ 123.816503] CM = 1, WnR = 1 [ 123.819455] user pgtable: 4k pages, 48-bit VAs, pgdp=0000000805047000 [ 123.825887] [00000000003fffc0] pgd=0000000803b45003, p4d=0000000803b45003, pud=0000000000000000 [ 123.834586] Internal error: Oops: 96000145 [#1] PREEMPT SMP Fixes: 1c26372e5aa9 ("spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework") Signed-off-by: Quanyang Wang Link: https://lore.kernel.org/r/20210416004652.2975446-6-quanyang.wang@windriver.com Signed-off-by: Mark Brown --- drivers/spi/spi-zynqmp-gqspi.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index 419bc1e6358b7a..328b6559bb19a2 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -733,7 +733,7 @@ static irqreturn_t zynqmp_qspi_irq(int irq, void *dev_id) * zynqmp_qspi_setuprxdma - This function sets up the RX DMA operation * @xqspi: xqspi is a pointer to the GQSPI instance. */ -static void zynqmp_qspi_setuprxdma(struct zynqmp_qspi *xqspi) +static int zynqmp_qspi_setuprxdma(struct zynqmp_qspi *xqspi) { u32 rx_bytes, rx_rem, config_reg; dma_addr_t addr; @@ -747,7 +747,7 @@ static void zynqmp_qspi_setuprxdma(struct zynqmp_qspi *xqspi) zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg); xqspi->mode = GQSPI_MODE_IO; xqspi->dma_rx_bytes = 0; - return; + return 0; } rx_rem = xqspi->bytes_to_receive % 4; @@ -755,8 +755,10 @@ static void zynqmp_qspi_setuprxdma(struct zynqmp_qspi *xqspi) addr = dma_map_single(xqspi->dev, (void *)xqspi->rxbuf, rx_bytes, DMA_FROM_DEVICE); - if (dma_mapping_error(xqspi->dev, addr)) + if (dma_mapping_error(xqspi->dev, addr)) { dev_err(xqspi->dev, "ERR:rxdma:memory not mapped\n"); + return -ENOMEM; + } xqspi->dma_rx_bytes = rx_bytes; xqspi->dma_addr = addr; @@ -777,6 +779,8 @@ static void zynqmp_qspi_setuprxdma(struct zynqmp_qspi *xqspi) /* Write the number of bytes to transfer */ zynqmp_gqspi_write(xqspi, GQSPI_QSPIDMA_DST_SIZE_OFST, rx_bytes); + + return 0; } /** @@ -813,11 +817,17 @@ static void zynqmp_qspi_write_op(struct zynqmp_qspi *xqspi, u8 tx_nbits, * @genfifoentry: genfifoentry is pointer to the variable in which * GENFIFO mask is returned to calling function */ -static void zynqmp_qspi_read_op(struct zynqmp_qspi *xqspi, u8 rx_nbits, +static int zynqmp_qspi_read_op(struct zynqmp_qspi *xqspi, u8 rx_nbits, u32 genfifoentry) { - zynqmp_qspi_setuprxdma(xqspi); + int ret; + + ret = zynqmp_qspi_setuprxdma(xqspi); + if (ret) + return ret; zynqmp_qspi_fillgenfifo(xqspi, rx_nbits, genfifoentry); + + return 0; } /** @@ -1031,8 +1041,11 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem, xqspi->rxbuf = (u8 *)op->data.buf.in; xqspi->bytes_to_receive = op->data.nbytes; xqspi->bytes_to_transfer = 0; - zynqmp_qspi_read_op(xqspi, op->data.buswidth, + err = zynqmp_qspi_read_op(xqspi, op->data.buswidth, genfifoentry); + if (err) + goto return_err; + zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, zynqmp_gqspi_read (xqspi, GQSPI_CONFIG_OFST) | @@ -1159,6 +1172,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) goto clk_dis_all; } + dma_set_mask(&pdev->dev, DMA_BIT_MASK(44)); ctlr->bits_per_word_mask = SPI_BPW_MASK(8); ctlr->num_chipselect = GQSPI_DEFAULT_NUM_CS; ctlr->mem_ops = &zynqmp_qspi_mem_ops; From 102e9d1936569d43f55dd1ea89be355ad207143c Mon Sep 17 00:00:00 2001 From: Christophe Kerello Date: Mon, 19 Apr 2021 14:15:39 +0200 Subject: [PATCH 098/113] spi: stm32-qspi: fix pm_runtime usage_count counter pm_runtime usage_count counter is not well managed. pm_runtime_put_autosuspend callback drops the usage_counter but this one has never been increased. Add pm_runtime_get_sync callback to bump up the usage counter. It is also needed to use pm_runtime_force_suspend and pm_runtime_force_resume APIs to handle properly the clock. Fixes: 9d282c17b023 ("spi: stm32-qspi: Add pm_runtime support") Signed-off-by: Christophe Kerello Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210419121541.11617-2-patrice.chotard@foss.st.com Signed-off-by: Mark Brown --- drivers/spi/spi-stm32-qspi.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c index 947e6b9dc9f4d5..2786470a52011f 100644 --- a/drivers/spi/spi-stm32-qspi.c +++ b/drivers/spi/spi-stm32-qspi.c @@ -727,21 +727,31 @@ static int __maybe_unused stm32_qspi_suspend(struct device *dev) { pinctrl_pm_select_sleep_state(dev); - return 0; + return pm_runtime_force_suspend(dev); } static int __maybe_unused stm32_qspi_resume(struct device *dev) { struct stm32_qspi *qspi = dev_get_drvdata(dev); + int ret; + + ret = pm_runtime_force_resume(dev); + if (ret < 0) + return ret; pinctrl_pm_select_default_state(dev); - clk_prepare_enable(qspi->clk); + + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + pm_runtime_put_noidle(dev); + return ret; + } writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR); writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR); - pm_runtime_mark_last_busy(qspi->dev); - pm_runtime_put_autosuspend(qspi->dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); return 0; } From f3530f26f8e9869e6e8c3370cf6f61330774fe2b Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Mon, 19 Apr 2021 14:15:40 +0200 Subject: [PATCH 099/113] spi: stm32-qspi: Trigger DMA only if more than 4 bytes to transfer In order to optimize accesses to spi flashes, trigger a DMA only if more than 4 bytes has to be transferred. DMA transfer preparation's cost becomes negligible above 4 bytes to transfer. Below this threshold, indirect transfer give more throughput. mtd_speedtest shows that page write throughtput increases : - from 779 to 853 KiB/s (~9.5%) with s25fl512s SPI-NOR. - from 5283 to 5666 KiB/s (~7.25%) with Micron SPI-NAND. Signed-off-by: Christophe Kerello Signed-off-by: Patrice Chotard Link: https://lore.kernel.org/r/20210419121541.11617-3-patrice.chotard@foss.st.com Signed-off-by: Mark Brown --- drivers/spi/spi-stm32-qspi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c index 2786470a52011f..6e74d6bed54c3f 100644 --- a/drivers/spi/spi-stm32-qspi.c +++ b/drivers/spi/spi-stm32-qspi.c @@ -269,8 +269,9 @@ static int stm32_qspi_tx(struct stm32_qspi *qspi, const struct spi_mem_op *op) if (qspi->fmode == CCR_FMODE_MM) return stm32_qspi_tx_mm(qspi, op); - else if ((op->data.dir == SPI_MEM_DATA_IN && qspi->dma_chrx) || - (op->data.dir == SPI_MEM_DATA_OUT && qspi->dma_chtx)) + else if (((op->data.dir == SPI_MEM_DATA_IN && qspi->dma_chrx) || + (op->data.dir == SPI_MEM_DATA_OUT && qspi->dma_chtx)) && + op->data.nbytes > 4) if (!stm32_qspi_tx_dma(qspi, op)) return 0; From 18674dee3cd651279eb3d9ba789fe483ddfe1137 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Mon, 19 Apr 2021 14:15:41 +0200 Subject: [PATCH 100/113] spi: stm32-qspi: Add dirmap support Add stm32_qspi_dirmap_read() and stm32_qspi_dirmap_create() to get dirmap support. Update the exec_op callback which doens't allow anymore memory map access. Memory map access are only available through the dirmap_read callback. Signed-off-by: Patrice Chotard Link: https://lore.kernel.org/r/20210419121541.11617-4-patrice.chotard@foss.st.com Signed-off-by: Mark Brown --- drivers/spi/spi-stm32-qspi.c | 83 +++++++++++++++++++++++++++++------- 1 file changed, 67 insertions(+), 16 deletions(-) diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c index 6e74d6bed54c3f..e2a99f05455187 100644 --- a/drivers/spi/spi-stm32-qspi.c +++ b/drivers/spi/spi-stm32-qspi.c @@ -331,7 +331,7 @@ static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) { struct stm32_qspi *qspi = spi_controller_get_devdata(mem->spi->master); struct stm32_qspi_flash *flash = &qspi->flash[mem->spi->chip_select]; - u32 ccr, cr, addr_max; + u32 ccr, cr; int timeout, err = 0; dev_dbg(qspi->dev, "cmd:%#x mode:%d.%d.%d.%d addr:%#llx len:%#x\n", @@ -343,18 +343,6 @@ static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) if (err) goto abort; - addr_max = op->addr.val + op->data.nbytes + 1; - - if (op->data.dir == SPI_MEM_DATA_IN) { - if (addr_max < qspi->mm_size && - op->addr.buswidth) - qspi->fmode = CCR_FMODE_MM; - else - qspi->fmode = CCR_FMODE_INDR; - } else { - qspi->fmode = CCR_FMODE_INDW; - } - cr = readl_relaxed(qspi->io_base + QSPI_CR); cr &= ~CR_PRESC_MASK & ~CR_FSEL; cr |= FIELD_PREP(CR_PRESC_MASK, flash->presc); @@ -364,8 +352,6 @@ static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) if (op->data.nbytes) writel_relaxed(op->data.nbytes - 1, qspi->io_base + QSPI_DLR); - else - qspi->fmode = CCR_FMODE_INDW; ccr = qspi->fmode; ccr |= FIELD_PREP(CCR_INST_MASK, op->cmd.opcode); @@ -441,6 +427,11 @@ static int stm32_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) } mutex_lock(&qspi->lock); + if (op->data.dir == SPI_MEM_DATA_IN && op->data.nbytes) + qspi->fmode = CCR_FMODE_INDR; + else + qspi->fmode = CCR_FMODE_INDW; + ret = stm32_qspi_send(mem, op); mutex_unlock(&qspi->lock); @@ -450,6 +441,64 @@ static int stm32_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) return ret; } +static int stm32_qspi_dirmap_create(struct spi_mem_dirmap_desc *desc) +{ + struct stm32_qspi *qspi = spi_controller_get_devdata(desc->mem->spi->master); + + if (desc->info.op_tmpl.data.dir == SPI_MEM_DATA_OUT) + return -EOPNOTSUPP; + + /* should never happen, as mm_base == null is an error probe exit condition */ + if (!qspi->mm_base && desc->info.op_tmpl.data.dir == SPI_MEM_DATA_IN) + return -EOPNOTSUPP; + + if (!qspi->mm_size) + return -EOPNOTSUPP; + + return 0; +} + +static ssize_t stm32_qspi_dirmap_read(struct spi_mem_dirmap_desc *desc, + u64 offs, size_t len, void *buf) +{ + struct stm32_qspi *qspi = spi_controller_get_devdata(desc->mem->spi->master); + struct spi_mem_op op; + u32 addr_max; + int ret; + + ret = pm_runtime_get_sync(qspi->dev); + if (ret < 0) { + pm_runtime_put_noidle(qspi->dev); + return ret; + } + + mutex_lock(&qspi->lock); + /* make a local copy of desc op_tmpl and complete dirmap rdesc + * spi_mem_op template with offs, len and *buf in order to get + * all needed transfer information into struct spi_mem_op + */ + memcpy(&op, &desc->info.op_tmpl, sizeof(struct spi_mem_op)); + dev_dbg(qspi->dev, "%s len = 0x%x offs = 0x%llx buf = 0x%p\n", __func__, len, offs, buf); + + op.data.nbytes = len; + op.addr.val = desc->info.offset + offs; + op.data.buf.in = buf; + + addr_max = op.addr.val + op.data.nbytes + 1; + if (addr_max < qspi->mm_size && op.addr.buswidth) + qspi->fmode = CCR_FMODE_MM; + else + qspi->fmode = CCR_FMODE_INDR; + + ret = stm32_qspi_send(desc->mem, &op); + mutex_unlock(&qspi->lock); + + pm_runtime_mark_last_busy(qspi->dev); + pm_runtime_put_autosuspend(qspi->dev); + + return ret ?: len; +} + static int stm32_qspi_setup(struct spi_device *spi) { struct spi_controller *ctrl = spi->master; @@ -555,7 +604,9 @@ static void stm32_qspi_dma_free(struct stm32_qspi *qspi) * to check supported mode. */ static const struct spi_controller_mem_ops stm32_qspi_mem_ops = { - .exec_op = stm32_qspi_exec_op, + .exec_op = stm32_qspi_exec_op, + .dirmap_create = stm32_qspi_dirmap_create, + .dirmap_read = stm32_qspi_dirmap_read, }; static int stm32_qspi_probe(struct platform_device *pdev) From d347b4aaa1a042ea528e385d9070b74c77a14321 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Fri, 16 Apr 2021 21:59:56 +0200 Subject: [PATCH 101/113] spi: sync up initial chipselect state When initially probing the SPI slave device, the call for disabling an SPI device without the SPI_CS_HIGH flag is not applied, as the condition for checking whether or not the state to be applied equals the one currently set evaluates to true. This however might not necessarily be the case, as the chipselect might be active. Add a force flag to spi_set_cs which allows to override this early exit condition. Set it to false everywhere except when called from spi_setup to sync up the initial CS state. Fixes commit d40f0b6f2e21 ("spi: Avoid setting the chip select if we don't need to") Signed-off-by: David Bauer Link: https://lore.kernel.org/r/20210416195956.121811-1-mail@david-bauer.net Signed-off-by: Mark Brown --- drivers/spi/spi.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 5e9d636777a2d7..cf231ff467810e 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -786,7 +786,7 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) /*-------------------------------------------------------------------------*/ -static void spi_set_cs(struct spi_device *spi, bool enable) +static void spi_set_cs(struct spi_device *spi, bool enable, bool force) { bool enable1 = enable; @@ -794,7 +794,7 @@ static void spi_set_cs(struct spi_device *spi, bool enable) * Avoid calling into the driver (or doing delays) if the chip select * isn't actually changing from the last time this was called. */ - if ((spi->controller->last_cs_enable == enable) && + if (!force && (spi->controller->last_cs_enable == enable) && (spi->controller->last_cs_mode_high == (spi->mode & SPI_CS_HIGH))) return; @@ -1244,7 +1244,7 @@ static int spi_transfer_one_message(struct spi_controller *ctlr, struct spi_statistics *statm = &ctlr->statistics; struct spi_statistics *stats = &msg->spi->statistics; - spi_set_cs(msg->spi, true); + spi_set_cs(msg->spi, true, false); SPI_STATISTICS_INCREMENT_FIELD(statm, messages); SPI_STATISTICS_INCREMENT_FIELD(stats, messages); @@ -1312,9 +1312,9 @@ static int spi_transfer_one_message(struct spi_controller *ctlr, &msg->transfers)) { keep_cs = true; } else { - spi_set_cs(msg->spi, false); + spi_set_cs(msg->spi, false, false); _spi_transfer_cs_change_delay(msg, xfer); - spi_set_cs(msg->spi, true); + spi_set_cs(msg->spi, true, false); } } @@ -1323,7 +1323,7 @@ static int spi_transfer_one_message(struct spi_controller *ctlr, out: if (ret != 0 || !keep_cs) - spi_set_cs(msg->spi, false); + spi_set_cs(msg->spi, false, false); if (msg->status == -EINPROGRESS) msg->status = ret; @@ -3399,11 +3399,11 @@ int spi_setup(struct spi_device *spi) */ status = 0; - spi_set_cs(spi, false); + spi_set_cs(spi, false, true); pm_runtime_mark_last_busy(spi->controller->dev.parent); pm_runtime_put_autosuspend(spi->controller->dev.parent); } else { - spi_set_cs(spi, false); + spi_set_cs(spi, false, true); } mutex_unlock(&spi->controller->io_mutex); From c914dbf88fa8619602e0913e8a952a19631ed195 Mon Sep 17 00:00:00 2001 From: Joe Burmeister Date: Mon, 19 Apr 2021 14:06:31 +0100 Subject: [PATCH 102/113] spi: Handle SPI device setup callback failure. If the setup callback failed, but the controller has auto_runtime_pm and set_cs, the setup failure could be missed. Signed-off-by: Joe Burmeister Link: https://lore.kernel.org/r/20210419130631.4586-1-joe.burmeister@devtank.co.uk Signed-off-by: Mark Brown --- drivers/spi/spi.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index cf231ff467810e..cc6d43d7895f02 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -3378,8 +3378,15 @@ int spi_setup(struct spi_device *spi) mutex_lock(&spi->controller->io_mutex); - if (spi->controller->setup) + if (spi->controller->setup) { status = spi->controller->setup(spi); + if (status) { + mutex_unlock(&spi->controller->io_mutex); + dev_err(&spi->controller->dev, "Failed to setup device: %d\n", + status); + return status; + } + } if (spi->controller->auto_runtime_pm && spi->controller->set_cs) { status = pm_runtime_get_sync(spi->controller->dev.parent); From 1b8a7d4282c038b3846f2485d86cb990c55c38d9 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 20 Apr 2021 10:21:03 +0200 Subject: [PATCH 103/113] spi: stm32-qspi: Fix compilation warning in ARM64 This fixes warnings detected when compiling in ARM64. Introduced by 'commit 18674dee3cd6 ("spi: stm32-qspi: Add dirmap support")' Signed-off-by: Patrice Chotard Link: https://lore.kernel.org/r/20210420082103.1693-1-patrice.chotard@foss.st.com Signed-off-by: Mark Brown --- drivers/spi/spi-stm32-qspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c index e2a99f05455187..02691c1603d943 100644 --- a/drivers/spi/spi-stm32-qspi.c +++ b/drivers/spi/spi-stm32-qspi.c @@ -478,7 +478,7 @@ static ssize_t stm32_qspi_dirmap_read(struct spi_mem_dirmap_desc *desc, * all needed transfer information into struct spi_mem_op */ memcpy(&op, &desc->info.op_tmpl, sizeof(struct spi_mem_op)); - dev_dbg(qspi->dev, "%s len = 0x%x offs = 0x%llx buf = 0x%p\n", __func__, len, offs, buf); + dev_dbg(qspi->dev, "%s len = 0x%lx offs = 0x%llx buf = 0x%p\n", __func__, len, offs, buf); op.data.nbytes = len; op.addr.val = desc->info.offset + offs; From b0c3d9354de1f87eebc00694d5218b6611265933 Mon Sep 17 00:00:00 2001 From: Matthew Gerlach Date: Fri, 16 Apr 2021 09:57:19 -0700 Subject: [PATCH 104/113] spi: altera: separate core code from platform code In preparation of adding support for a new bus type, separate the core spi-altera code from the platform driver code. Signed-off-by: Matthew Gerlach Link: https://lore.kernel.org/r/20210416165720.554144-2-matthew.gerlach@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 9 +- drivers/spi/Makefile | 3 +- .../spi/{spi-altera.c => spi-altera-core.c} | 166 +---------------- drivers/spi/spi-altera-platform.c | 172 ++++++++++++++++++ include/linux/spi/altera.h | 21 +++ 5 files changed, 208 insertions(+), 163 deletions(-) rename drivers/spi/{spi-altera.c => spi-altera-core.c} (56%) create mode 100644 drivers/spi/spi-altera-platform.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 853cf4c46e5e4a..e59f548e882aff 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -58,11 +58,18 @@ config SPI_MEM comment "SPI Master Controller Drivers" config SPI_ALTERA - tristate "Altera SPI Controller" + tristate "Altera SPI Controller platform driver" + select SPI_ALTERA_CORE select REGMAP_MMIO help This is the driver for the Altera SPI Controller. +config SPI_ALTERA_CORE + tristate "Altera SPI Controller core code" + select REGMAP + help + "The core code for the Altera SPI Controller" + config SPI_AR934X tristate "Qualcomm Atheros AR934X/QCA95XX SPI controller driver" depends on ATH79 || COMPILE_TEST diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 29fee71022b41b..e6be348ca20785 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -14,7 +14,8 @@ obj-$(CONFIG_SPI_SPIDEV) += spidev.o obj-$(CONFIG_SPI_LOOPBACK_TEST) += spi-loopback-test.o # SPI master controller drivers (bus) -obj-$(CONFIG_SPI_ALTERA) += spi-altera.o +obj-$(CONFIG_SPI_ALTERA) += spi-altera-platform.o +obj-$(CONFIG_SPI_ALTERA_CORE) += spi-altera-core.o obj-$(CONFIG_SPI_AR934X) += spi-ar934x.o obj-$(CONFIG_SPI_ARMADA_3700) += spi-armada-3700.o obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera-core.c similarity index 56% rename from drivers/spi/spi-altera.c rename to drivers/spi/spi-altera-core.c index 62ea0c9e321b4c..de4d31c530d900 100644 --- a/drivers/spi/spi-altera.c +++ b/drivers/spi/spi-altera-core.c @@ -10,7 +10,6 @@ * Ben Dooks */ -#include #include #include #include @@ -41,36 +40,6 @@ #define ALTERA_SPI_CONTROL_IE_MSK 0x100 #define ALTERA_SPI_CONTROL_SSO_MSK 0x400 -#define ALTERA_SPI_MAX_CS 32 - -enum altera_spi_type { - ALTERA_SPI_TYPE_UNKNOWN, - ALTERA_SPI_TYPE_SUBDEV, -}; - -struct altera_spi { - int irq; - int len; - int count; - int bytes_per_word; - u32 imr; - - /* data buffers */ - const unsigned char *tx; - unsigned char *rx; - - struct regmap *regmap; - u32 regoff; - struct device *dev; -}; - -static const struct regmap_config spi_altera_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .fast_io = true, -}; - static int altr_spi_writel(struct altera_spi *hw, unsigned int reg, unsigned int val) { @@ -211,7 +180,7 @@ static int altera_spi_txrx(struct spi_master *master, return 0; } -static irqreturn_t altera_spi_irq(int irq, void *dev) +irqreturn_t altera_spi_irq(int irq, void *dev) { struct spi_master *master = dev; struct altera_spi *hw = spi_master_get_devdata(master); @@ -230,84 +199,16 @@ static irqreturn_t altera_spi_irq(int irq, void *dev) return IRQ_HANDLED; } +EXPORT_SYMBOL_GPL(altera_spi_irq); -static int altera_spi_probe(struct platform_device *pdev) +void altera_spi_init_master(struct spi_master *master) { - const struct platform_device_id *platid = platform_get_device_id(pdev); - struct altera_spi_platform_data *pdata = dev_get_platdata(&pdev->dev); - enum altera_spi_type type = ALTERA_SPI_TYPE_UNKNOWN; - struct altera_spi *hw; - struct spi_master *master; - int err = -ENODEV; + struct altera_spi *hw = spi_master_get_devdata(master); u32 val; - u16 i; - - master = spi_alloc_master(&pdev->dev, sizeof(struct altera_spi)); - if (!master) - return err; - - /* setup the master state. */ - master->bus_num = pdev->id; - - if (pdata) { - if (pdata->num_chipselect > ALTERA_SPI_MAX_CS) { - dev_err(&pdev->dev, - "Invalid number of chipselect: %hu\n", - pdata->num_chipselect); - err = -EINVAL; - goto exit; - } - master->num_chipselect = pdata->num_chipselect; - master->mode_bits = pdata->mode_bits; - master->bits_per_word_mask = pdata->bits_per_word_mask; - } else { - master->num_chipselect = 16; - master->mode_bits = SPI_CS_HIGH; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16); - } - - master->dev.of_node = pdev->dev.of_node; master->transfer_one = altera_spi_txrx; master->set_cs = altera_spi_set_cs; - hw = spi_master_get_devdata(master); - hw->dev = &pdev->dev; - - if (platid) - type = platid->driver_data; - - /* find and map our resources */ - if (type == ALTERA_SPI_TYPE_SUBDEV) { - struct resource *regoff; - - hw->regmap = dev_get_regmap(pdev->dev.parent, NULL); - if (!hw->regmap) { - dev_err(&pdev->dev, "get regmap failed\n"); - goto exit; - } - - regoff = platform_get_resource(pdev, IORESOURCE_REG, 0); - if (regoff) - hw->regoff = regoff->start; - } else { - void __iomem *res; - - res = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(res)) { - err = PTR_ERR(res); - goto exit; - } - - hw->regmap = devm_regmap_init_mmio(&pdev->dev, res, - &spi_altera_config); - if (IS_ERR(hw->regmap)) { - dev_err(&pdev->dev, "regmap mmio init failed\n"); - err = PTR_ERR(hw->regmap); - goto exit; - } - } - /* program defaults into the registers */ hw->imr = 0; /* disable spi interrupts */ altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr); @@ -315,64 +216,7 @@ static int altera_spi_probe(struct platform_device *pdev) altr_spi_readl(hw, ALTERA_SPI_STATUS, &val); if (val & ALTERA_SPI_STATUS_RRDY_MSK) altr_spi_readl(hw, ALTERA_SPI_RXDATA, &val); /* flush rxdata */ - /* irq is optional */ - hw->irq = platform_get_irq(pdev, 0); - if (hw->irq >= 0) { - err = devm_request_irq(&pdev->dev, hw->irq, altera_spi_irq, 0, - pdev->name, master); - if (err) - goto exit; - } - - err = devm_spi_register_master(&pdev->dev, master); - if (err) - goto exit; - - if (pdata) { - for (i = 0; i < pdata->num_devices; i++) { - if (!spi_new_device(master, pdata->devices + i)) - dev_warn(&pdev->dev, - "unable to create SPI device: %s\n", - pdata->devices[i].modalias); - } - } - - dev_info(&pdev->dev, "regoff %u, irq %d\n", hw->regoff, hw->irq); - - return 0; -exit: - spi_master_put(master); - return err; } +EXPORT_SYMBOL_GPL(altera_spi_init_master); -#ifdef CONFIG_OF -static const struct of_device_id altera_spi_match[] = { - { .compatible = "ALTR,spi-1.0", }, - { .compatible = "altr,spi-1.0", }, - {}, -}; -MODULE_DEVICE_TABLE(of, altera_spi_match); -#endif /* CONFIG_OF */ - -static const struct platform_device_id altera_spi_ids[] = { - { DRV_NAME, ALTERA_SPI_TYPE_UNKNOWN }, - { "subdev_spi_altera", ALTERA_SPI_TYPE_SUBDEV }, - { } -}; -MODULE_DEVICE_TABLE(platform, altera_spi_ids); - -static struct platform_driver altera_spi_driver = { - .probe = altera_spi_probe, - .driver = { - .name = DRV_NAME, - .pm = NULL, - .of_match_table = of_match_ptr(altera_spi_match), - }, - .id_table = altera_spi_ids, -}; -module_platform_driver(altera_spi_driver); - -MODULE_DESCRIPTION("Altera SPI driver"); -MODULE_AUTHOR("Thomas Chou "); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" DRV_NAME); diff --git a/drivers/spi/spi-altera-platform.c b/drivers/spi/spi-altera-platform.c new file mode 100644 index 00000000000000..f7a7c14e36790e --- /dev/null +++ b/drivers/spi/spi-altera-platform.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Altera SPI driver + * + * Copyright (C) 2008 Thomas Chou + * + * Based on spi_s3c24xx.c, which is: + * Copyright (c) 2006 Ben Dooks + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "spi_altera" + +enum altera_spi_type { + ALTERA_SPI_TYPE_UNKNOWN, + ALTERA_SPI_TYPE_SUBDEV, +}; + +static const struct regmap_config spi_altera_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, +}; + +static int altera_spi_probe(struct platform_device *pdev) +{ + const struct platform_device_id *platid = platform_get_device_id(pdev); + struct altera_spi_platform_data *pdata = dev_get_platdata(&pdev->dev); + enum altera_spi_type type = ALTERA_SPI_TYPE_UNKNOWN; + struct altera_spi *hw; + struct spi_master *master; + int err = -ENODEV; + u16 i; + + master = spi_alloc_master(&pdev->dev, sizeof(struct altera_spi)); + if (!master) + return err; + + /* setup the master state. */ + master->bus_num = pdev->id; + + if (pdata) { + if (pdata->num_chipselect > ALTERA_SPI_MAX_CS) { + dev_err(&pdev->dev, + "Invalid number of chipselect: %u\n", + pdata->num_chipselect); + err = -EINVAL; + goto exit; + } + + master->num_chipselect = pdata->num_chipselect; + master->mode_bits = pdata->mode_bits; + master->bits_per_word_mask = pdata->bits_per_word_mask; + } else { + master->num_chipselect = 16; + master->mode_bits = SPI_CS_HIGH; + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16); + } + + master->dev.of_node = pdev->dev.of_node; + + hw = spi_master_get_devdata(master); + hw->dev = &pdev->dev; + + if (platid) + type = platid->driver_data; + + /* find and map our resources */ + if (type == ALTERA_SPI_TYPE_SUBDEV) { + struct resource *regoff; + + hw->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!hw->regmap) { + dev_err(&pdev->dev, "get regmap failed\n"); + goto exit; + } + + regoff = platform_get_resource(pdev, IORESOURCE_REG, 0); + if (regoff) + hw->regoff = regoff->start; + } else { + void __iomem *res; + + res = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(res)) { + err = PTR_ERR(res); + goto exit; + } + + hw->regmap = devm_regmap_init_mmio(&pdev->dev, res, + &spi_altera_config); + if (IS_ERR(hw->regmap)) { + dev_err(&pdev->dev, "regmap mmio init failed\n"); + err = PTR_ERR(hw->regmap); + goto exit; + } + } + + altera_spi_init_master(master); + + /* irq is optional */ + hw->irq = platform_get_irq(pdev, 0); + if (hw->irq >= 0) { + err = devm_request_irq(&pdev->dev, hw->irq, altera_spi_irq, 0, + pdev->name, master); + if (err) + goto exit; + } + + err = devm_spi_register_master(&pdev->dev, master); + if (err) + goto exit; + + if (pdata) { + for (i = 0; i < pdata->num_devices; i++) { + if (!spi_new_device(master, pdata->devices + i)) + dev_warn(&pdev->dev, + "unable to create SPI device: %s\n", + pdata->devices[i].modalias); + } + } + + dev_info(&pdev->dev, "regoff %u, irq %d\n", hw->regoff, hw->irq); + + return 0; +exit: + spi_master_put(master); + return err; +} + +#ifdef CONFIG_OF +static const struct of_device_id altera_spi_match[] = { + { .compatible = "ALTR,spi-1.0", }, + { .compatible = "altr,spi-1.0", }, + {}, +}; +MODULE_DEVICE_TABLE(of, altera_spi_match); +#endif /* CONFIG_OF */ + +static const struct platform_device_id altera_spi_ids[] = { + { DRV_NAME, ALTERA_SPI_TYPE_UNKNOWN }, + { "subdev_spi_altera", ALTERA_SPI_TYPE_SUBDEV }, + { } +}; +MODULE_DEVICE_TABLE(platform, altera_spi_ids); + +static struct platform_driver altera_spi_driver = { + .probe = altera_spi_probe, + .driver = { + .name = DRV_NAME, + .pm = NULL, + .of_match_table = of_match_ptr(altera_spi_match), + }, + .id_table = altera_spi_ids, +}; +module_platform_driver(altera_spi_driver); + +MODULE_DESCRIPTION("Altera SPI driver"); +MODULE_AUTHOR("Thomas Chou "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/include/linux/spi/altera.h b/include/linux/spi/altera.h index 2d42641499a6e0..2e2a622e56da97 100644 --- a/include/linux/spi/altera.h +++ b/include/linux/spi/altera.h @@ -5,10 +5,13 @@ #ifndef __LINUX_SPI_ALTERA_H #define __LINUX_SPI_ALTERA_H +#include #include #include #include +#define ALTERA_SPI_MAX_CS 32 + /** * struct altera_spi_platform_data - Platform data of the Altera SPI driver * @mode_bits: Mode bits of SPI master. @@ -26,4 +29,22 @@ struct altera_spi_platform_data { struct spi_board_info *devices; }; +struct altera_spi { + int irq; + int len; + int count; + int bytes_per_word; + u32 imr; + + /* data buffers */ + const unsigned char *tx; + unsigned char *rx; + + struct regmap *regmap; + u32 regoff; + struct device *dev; +}; + +extern irqreturn_t altera_spi_irq(int irq, void *dev); +extern void altera_spi_init_master(struct spi_master *master); #endif /* __LINUX_SPI_ALTERA_H */ From ba2fc167e9447596a812e828842d0130ea9cd0e4 Mon Sep 17 00:00:00 2001 From: Matthew Gerlach Date: Fri, 16 Apr 2021 09:57:20 -0700 Subject: [PATCH 105/113] spi: altera: Add DFL bus driver for Altera API Controller This patch adds a Device Feature List (DFL) bus driver for the Altera SPI Master controller. The SPI master is connected to an Intel SPI Slave to Avalon Bridge inside an Intel MAX10 BMC Chip. Signed-off-by: Matthew Gerlach Link: https://lore.kernel.org/r/20210416165720.554144-3-matthew.gerlach@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 9 ++ drivers/spi/Makefile | 1 + drivers/spi/spi-altera-dfl.c | 204 +++++++++++++++++++++++++++++++++++ 3 files changed, 214 insertions(+) create mode 100644 drivers/spi/spi-altera-dfl.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index e59f548e882aff..8b161ec4943bfe 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -70,6 +70,15 @@ config SPI_ALTERA_CORE help "The core code for the Altera SPI Controller" +config SPI_ALTERA_DFL + tristate "DFL bus driver for Altera SPI Controller" + depends on FPGA_DFL + select SPI_ALTERA_CORE + help + This is a Device Feature List (DFL) bus driver for the + Altera SPI master controller. The SPI master is connected + to a SPI slave to Avalon bridge in a Intel MAX BMC. + config SPI_AR934X tristate "Qualcomm Atheros AR934X/QCA95XX SPI controller driver" depends on ATH79 || COMPILE_TEST diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index e6be348ca20785..13e54c45e9df07 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_LOOPBACK_TEST) += spi-loopback-test.o # SPI master controller drivers (bus) obj-$(CONFIG_SPI_ALTERA) += spi-altera-platform.o obj-$(CONFIG_SPI_ALTERA_CORE) += spi-altera-core.o +obj-$(CONFIG_SPI_ALTERA_DFL) += spi-altera-dfl.o obj-$(CONFIG_SPI_AR934X) += spi-ar934x.o obj-$(CONFIG_SPI_ARMADA_3700) += spi-armada-3700.o obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o diff --git a/drivers/spi/spi-altera-dfl.c b/drivers/spi/spi-altera-dfl.c new file mode 100644 index 00000000000000..3e32e4fe589503 --- /dev/null +++ b/drivers/spi/spi-altera-dfl.c @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// DFL bus driver for Altera SPI Master +// +// Copyright (C) 2020 Intel Corporation, Inc. +// +// Authors: +// Matthew Gerlach +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FME_FEATURE_ID_MAX10_SPI 0xe +#define FME_FEATURE_REV_MAX10_SPI_N5010 0x1 + +#define SPI_CORE_PARAMETER 0x8 +#define SHIFT_MODE BIT_ULL(1) +#define SHIFT_MODE_MSB 0 +#define SHIFT_MODE_LSB 1 +#define DATA_WIDTH GENMASK_ULL(7, 2) +#define NUM_CHIPSELECT GENMASK_ULL(13, 8) +#define CLK_POLARITY BIT_ULL(14) +#define CLK_PHASE BIT_ULL(15) +#define PERIPHERAL_ID GENMASK_ULL(47, 32) +#define SPI_CLK GENMASK_ULL(31, 22) +#define SPI_INDIRECT_ACC_OFST 0x10 + +#define INDIRECT_ADDR (SPI_INDIRECT_ACC_OFST+0x0) +#define INDIRECT_WR BIT_ULL(8) +#define INDIRECT_RD BIT_ULL(9) +#define INDIRECT_RD_DATA (SPI_INDIRECT_ACC_OFST+0x8) +#define INDIRECT_DATA_MASK GENMASK_ULL(31, 0) +#define INDIRECT_DEBUG BIT_ULL(32) +#define INDIRECT_WR_DATA (SPI_INDIRECT_ACC_OFST+0x10) +#define INDIRECT_TIMEOUT 10000 + +static int indirect_bus_reg_read(void *context, unsigned int reg, + unsigned int *val) +{ + void __iomem *base = context; + int loops; + u64 v; + + writeq((reg >> 2) | INDIRECT_RD, base + INDIRECT_ADDR); + + loops = 0; + while ((readq(base + INDIRECT_ADDR) & INDIRECT_RD) && + (loops++ < INDIRECT_TIMEOUT)) + cpu_relax(); + + if (loops >= INDIRECT_TIMEOUT) { + pr_err("%s timed out %d\n", __func__, loops); + return -ETIME; + } + + v = readq(base + INDIRECT_RD_DATA); + + *val = v & INDIRECT_DATA_MASK; + + return 0; +} + +static int indirect_bus_reg_write(void *context, unsigned int reg, + unsigned int val) +{ + void __iomem *base = context; + int loops; + + writeq(val, base + INDIRECT_WR_DATA); + writeq((reg >> 2) | INDIRECT_WR, base + INDIRECT_ADDR); + + loops = 0; + while ((readq(base + INDIRECT_ADDR) & INDIRECT_WR) && + (loops++ < INDIRECT_TIMEOUT)) + cpu_relax(); + + if (loops >= INDIRECT_TIMEOUT) { + pr_err("%s timed out %d\n", __func__, loops); + return -ETIME; + } + return 0; +} + +static const struct regmap_config indirect_regbus_cfg = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + .max_register = 24, + + .reg_write = indirect_bus_reg_write, + .reg_read = indirect_bus_reg_read, +}; + +static struct spi_board_info m10_bmc_info = { + .modalias = "m10-d5005", + .max_speed_hz = 12500000, + .bus_num = 0, + .chip_select = 0, +}; + +static void config_spi_master(void __iomem *base, struct spi_master *master) +{ + u64 v; + + v = readq(base + SPI_CORE_PARAMETER); + + master->mode_bits = SPI_CS_HIGH; + if (FIELD_GET(CLK_POLARITY, v)) + master->mode_bits |= SPI_CPOL; + if (FIELD_GET(CLK_PHASE, v)) + master->mode_bits |= SPI_CPHA; + + master->num_chipselect = FIELD_GET(NUM_CHIPSELECT, v); + master->bits_per_word_mask = + SPI_BPW_RANGE_MASK(1, FIELD_GET(DATA_WIDTH, v)); +} + +static int dfl_spi_altera_probe(struct dfl_device *dfl_dev) +{ + struct device *dev = &dfl_dev->dev; + struct spi_master *master; + struct altera_spi *hw; + void __iomem *base; + int err = -ENODEV; + + master = spi_alloc_master(dev, sizeof(struct altera_spi)); + if (!master) + return -ENOMEM; + + master->bus_num = dfl_dev->id; + + hw = spi_master_get_devdata(master); + + hw->dev = dev; + + base = devm_ioremap_resource(dev, &dfl_dev->mmio_res); + + if (IS_ERR(base)) { + dev_err(dev, "%s get mem resource fail!\n", __func__); + return PTR_ERR(base); + } + + config_spi_master(base, master); + dev_dbg(dev, "%s cs %u bpm 0x%x mode 0x%x\n", __func__, + master->num_chipselect, master->bits_per_word_mask, + master->mode_bits); + + hw->regmap = devm_regmap_init(dev, NULL, base, &indirect_regbus_cfg); + if (IS_ERR(hw->regmap)) + return PTR_ERR(hw->regmap); + + hw->irq = -EINVAL; + + altera_spi_init_master(master); + + err = devm_spi_register_master(dev, master); + if (err) { + dev_err(dev, "%s failed to register spi master %d\n", __func__, err); + goto exit; + } + + if (!spi_new_device(master, &m10_bmc_info)) { + dev_err(dev, "%s failed to create SPI device: %s\n", + __func__, m10_bmc_info.modalias); + } + + return 0; +exit: + spi_master_put(master); + return err; +} + +static const struct dfl_device_id dfl_spi_altera_ids[] = { + { FME_ID, FME_FEATURE_ID_MAX10_SPI }, + { } +}; + +static struct dfl_driver dfl_spi_altera_driver = { + .drv = { + .name = "dfl-spi-altera", + }, + .id_table = dfl_spi_altera_ids, + .probe = dfl_spi_altera_probe, +}; + +module_dfl_driver(dfl_spi_altera_driver); + +MODULE_DEVICE_TABLE(dfl, dfl_spi_altera_ids); +MODULE_DESCRIPTION("DFL spi altera driver"); +MODULE_AUTHOR("Intel Corporation"); +MODULE_LICENSE("GPL v2"); From 7d82f89c39ad3193893d36924fc1f8d44f3dc612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 16 Apr 2021 21:47:23 +0200 Subject: [PATCH 106/113] spi: brcm,spi-bcm-qspi: convert to the json-schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helps validating DTS files. Changes that require mentioning: 1. reg-names "mspi_regs" and "bspi_regs" were renamed to "mspi" and "bspi" as that is what's used in DTS files and in Linux driver 2. interrupt-names Names were reordered. "mspi_done" has to go first as it's always required. 3. spi-rx-bus-width Property description was dropped as it's part of the spi-controller.yaml 4. Examples: * drop partitions as they are well documented elsewhere * regs and interrupts were formatted and reordered to match yaml * <0x1c> was replaced with <&gic> * "m25p80" node name became "flash" * dropped invalid "m25p,fast-read" property * dropped undocumented and Linux-unused "clock-names" This rewritten binding validates cleanly using the "dt_binding_check". Some Linux stored DTS files will require reordering regs and interrupts to make dtbs_check happy. Signed-off-by: Rafał Miłecki Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20210416194723.23855-1-zajec5@gmail.com Signed-off-by: Mark Brown --- .../bindings/spi/brcm,spi-bcm-qspi.txt | 245 ------------------ .../bindings/spi/brcm,spi-bcm-qspi.yaml | 198 ++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 199 insertions(+), 246 deletions(-) delete mode 100644 Documentation/devicetree/bindings/spi/brcm,spi-bcm-qspi.txt create mode 100644 Documentation/devicetree/bindings/spi/brcm,spi-bcm-qspi.yaml diff --git a/Documentation/devicetree/bindings/spi/brcm,spi-bcm-qspi.txt b/Documentation/devicetree/bindings/spi/brcm,spi-bcm-qspi.txt deleted file mode 100644 index d99a9cf3336b6e..00000000000000 --- a/Documentation/devicetree/bindings/spi/brcm,spi-bcm-qspi.txt +++ /dev/null @@ -1,245 +0,0 @@ -Broadcom SPI controller - -The Broadcom SPI controller is a SPI master found on various SOCs, including -BRCMSTB (BCM7XXX), Cygnus, NSP and NS2. The Broadcom Master SPI hw IP consits -of : - MSPI : SPI master controller can read and write to a SPI slave device - BSPI : Broadcom SPI in combination with the MSPI hw IP provides acceleration - for flash reads and be configured to do single, double, quad lane - io with 3-byte and 4-byte addressing support. - - Supported Broadcom SoCs have one instance of MSPI+BSPI controller IP. - MSPI master can be used wihout BSPI. BRCMSTB SoCs have an additional instance - of a MSPI master without the BSPI to use with non flash slave devices that - use SPI protocol. - -Required properties: - -- #address-cells: - Must be <1>, as required by generic SPI binding. - -- #size-cells: - Must be <0>, also as required by generic SPI binding. - -- compatible: - Must be one of : - "brcm,spi-brcmstb-qspi", "brcm,spi-bcm-qspi" : MSPI+BSPI on BRCMSTB SoCs - "brcm,spi-brcmstb-mspi", "brcm,spi-bcm-qspi" : Second Instance of MSPI - BRCMSTB SoCs - "brcm,spi-bcm7425-qspi", "brcm,spi-bcm-qspi", "brcm,spi-brcmstb-mspi" : Second Instance of MSPI - BRCMSTB SoCs - "brcm,spi-bcm7429-qspi", "brcm,spi-bcm-qspi", "brcm,spi-brcmstb-mspi" : Second Instance of MSPI - BRCMSTB SoCs - "brcm,spi-bcm7435-qspi", "brcm,spi-bcm-qspi", "brcm,spi-brcmstb-mspi" : Second Instance of MSPI - BRCMSTB SoCs - "brcm,spi-bcm7445-qspi", "brcm,spi-bcm-qspi", "brcm,spi-brcmstb-mspi" : Second Instance of MSPI - BRCMSTB SoCs - "brcm,spi-bcm7216-qspi", "brcm,spi-bcm-qspi", "brcm,spi-brcmstb-mspi" : Second Instance of MSPI - BRCMSTB SoCs - "brcm,spi-bcm7278-qspi", "brcm,spi-bcm-qspi", "brcm,spi-brcmstb-mspi" : Second Instance of MSPI - BRCMSTB SoCs - "brcm,spi-nsp-qspi", "brcm,spi-bcm-qspi" : MSPI+BSPI on Cygnus, NSP - "brcm,spi-ns2-qspi", "brcm,spi-bcm-qspi" : NS2 SoCs - -- reg: - Define the bases and ranges of the associated I/O address spaces. - The required range is MSPI controller registers. - -- reg-names: - First name does not matter, but must be reserved for the MSPI controller - register range as mentioned in 'reg' above, and will typically contain - - "bspi_regs": BSPI register range, not required with compatible - "spi-brcmstb-mspi" - - "mspi_regs": MSPI register range is required for compatible strings - - "intr_regs", "intr_status_reg" : Interrupt and status register for - NSP, NS2, Cygnus SoC - -- interrupts - The interrupts used by the MSPI and/or BSPI controller. - -- interrupt-names: - Names of interrupts associated with MSPI - - "mspi_halted" : - - "mspi_done": Indicates that the requested SPI operation is complete. - - "spi_lr_fullness_reached" : Linear read BSPI pipe full - - "spi_lr_session_aborted" : Linear read BSPI pipe aborted - - "spi_lr_impatient" : Linear read BSPI requested when pipe empty - - "spi_lr_session_done" : Linear read BSPI session done - -- clocks: - A phandle to the reference clock for this block. - -Optional properties: - - -- native-endian - Defined when using BE SoC and device uses BE register read/write - -Recommended optional m25p80 properties: -- spi-rx-bus-width: Definition as per - Documentation/devicetree/bindings/spi/spi-bus.txt - -Examples: - -BRCMSTB SoC Example: - - SPI Master (MSPI+BSPI) for SPI-NOR access: - - spi@f03e3400 { - #address-cells = <0x1>; - #size-cells = <0x0>; - compatible = "brcm,spi-brcmstb-qspi", "brcm,spi-bcm-qspi"; - reg = <0xf03e0920 0x4 0xf03e3400 0x188 0xf03e3200 0x50>; - reg-names = "cs_reg", "mspi", "bspi"; - interrupts = <0x6 0x5 0x4 0x3 0x2 0x1 0x0>; - interrupt-parent = <0x1c>; - interrupt-names = "mspi_halted", - "mspi_done", - "spi_lr_overread", - "spi_lr_session_done", - "spi_lr_impatient", - "spi_lr_session_aborted", - "spi_lr_fullness_reached"; - - clocks = <&hif_spi>; - clock-names = "sw_spi"; - - m25p80@0 { - #size-cells = <0x2>; - #address-cells = <0x2>; - compatible = "m25p80"; - reg = <0x0>; - spi-max-frequency = <0x2625a00>; - spi-cpol; - spi-cpha; - m25p,fast-read; - - flash0.bolt@0 { - reg = <0x0 0x0 0x0 0x100000>; - }; - - flash0.macadr@100000 { - reg = <0x0 0x100000 0x0 0x10000>; - }; - - flash0.nvram@110000 { - reg = <0x0 0x110000 0x0 0x10000>; - }; - - flash0.kernel@120000 { - reg = <0x0 0x120000 0x0 0x400000>; - }; - - flash0.devtree@520000 { - reg = <0x0 0x520000 0x0 0x10000>; - }; - - flash0.splash@530000 { - reg = <0x0 0x530000 0x0 0x80000>; - }; - - flash0@0 { - reg = <0x0 0x0 0x0 0x4000000>; - }; - }; - }; - - - MSPI master for any SPI device : - - spi@f0416000 { - #address-cells = <1>; - #size-cells = <0>; - clocks = <&upg_fixed>; - compatible = "brcm,spi-brcmstb-mspi", "brcm,spi-bcm-qspi"; - reg = <0xf0416000 0x180>; - reg-names = "mspi"; - interrupts = <0x14>; - interrupt-parent = <&irq0_aon_intc>; - interrupt-names = "mspi_done"; - }; - -iProc SoC Example: - - qspi: spi@18027200 { - compatible = "brcm,spi-nsp-qspi", "brcm,spi-bcm-qspi"; - reg = <0x18027200 0x184>, - <0x18027000 0x124>, - <0x1811c408 0x004>, - <0x180273a0 0x01c>; - reg-names = "mspi_regs", "bspi_regs", "intr_regs", "intr_status_reg"; - interrupts = , - , - , - , - , - , - ; - interrupt-names = - "spi_lr_fullness_reached", - "spi_lr_session_aborted", - "spi_lr_impatient", - "spi_lr_session_done", - "mspi_done", - "mspi_halted"; - clocks = <&iprocmed>; - clock-names = "iprocmed"; - num-cs = <2>; - #address-cells = <1>; - #size-cells = <0>; - }; - - - NS2 SoC Example: - - qspi: spi@66470200 { - compatible = "brcm,spi-ns2-qspi", "brcm,spi-bcm-qspi"; - reg = <0x66470200 0x184>, - <0x66470000 0x124>, - <0x67017408 0x004>, - <0x664703a0 0x01c>; - reg-names = "mspi", "bspi", "intr_regs", - "intr_status_reg"; - interrupts = ; - interrupt-names = "spi_l1_intr"; - clocks = <&iprocmed>; - clock-names = "iprocmed"; - num-cs = <2>; - #address-cells = <1>; - #size-cells = <0>; - }; - - - m25p80 node for NSP, NS2 - - &qspi { - flash: m25p80@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "m25p80"; - reg = <0x0>; - spi-max-frequency = <12500000>; - m25p,fast-read; - spi-cpol; - spi-cpha; - - partition@0 { - label = "boot"; - reg = <0x00000000 0x000a0000>; - }; - - partition@a0000 { - label = "env"; - reg = <0x000a0000 0x00060000>; - }; - - partition@100000 { - label = "system"; - reg = <0x00100000 0x00600000>; - }; - - partition@700000 { - label = "rootfs"; - reg = <0x00700000 0x01900000>; - }; - }; diff --git a/Documentation/devicetree/bindings/spi/brcm,spi-bcm-qspi.yaml b/Documentation/devicetree/bindings/spi/brcm,spi-bcm-qspi.yaml new file mode 100644 index 00000000000000..6ee19d49fd3cce --- /dev/null +++ b/Documentation/devicetree/bindings/spi/brcm,spi-bcm-qspi.yaml @@ -0,0 +1,198 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/brcm,spi-bcm-qspi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom SPI controller + +maintainers: + - Kamal Dasu + - Rafał Miłecki + +description: | + The Broadcom SPI controller is a SPI master found on various SOCs, including + BRCMSTB (BCM7XXX), Cygnus, NSP and NS2. The Broadcom Master SPI hw IP consits + of: + MSPI : SPI master controller can read and write to a SPI slave device + BSPI : Broadcom SPI in combination with the MSPI hw IP provides acceleration + for flash reads and be configured to do single, double, quad lane + io with 3-byte and 4-byte addressing support. + + Supported Broadcom SoCs have one instance of MSPI+BSPI controller IP. + MSPI master can be used wihout BSPI. BRCMSTB SoCs have an additional instance + of a MSPI master without the BSPI to use with non flash slave devices that + use SPI protocol. + +allOf: + - $ref: spi-controller.yaml# + +properties: + compatible: + oneOf: + - description: Second Instance of MSPI BRCMSTB SoCs + items: + - enum: + - brcm,spi-bcm7425-qspi + - brcm,spi-bcm7429-qspi + - brcm,spi-bcm7435-qspi + - brcm,spi-bcm7445-qspi + - brcm,spi-bcm7216-qspi + - brcm,spi-bcm7278-qspi + - const: brcm,spi-bcm-qspi + - const: brcm,spi-brcmstb-mspi + - description: Second Instance of MSPI BRCMSTB SoCs + items: + - enum: + - brcm,spi-brcmstb-qspi + - brcm,spi-brcmstb-mspi + - brcm,spi-nsp-qspi + - brcm,spi-ns2-qspi + - const: brcm,spi-bcm-qspi + + reg: + minItems: 1 + maxItems: 5 + + reg-names: + minItems: 1 + maxItems: 5 + items: + - const: mspi + - const: bspi + - enum: [ intr_regs, intr_status_reg, cs_reg ] + - enum: [ intr_regs, intr_status_reg, cs_reg ] + - enum: [ intr_regs, intr_status_reg, cs_reg ] + + interrupts: + minItems: 1 + maxItems: 7 + + interrupt-names: + oneOf: + - minItems: 1 + maxItems: 7 + items: + - const: mspi_done + - const: mspi_halted + - const: spi_lr_fullness_reached + - const: spi_lr_session_aborted + - const: spi_lr_impatient + - const: spi_lr_session_done + - const: spi_lr_overread + - const: spi_l1_intr + + clocks: + maxItems: 1 + description: reference clock for this block + + native-endian: + $ref: /schemas/types.yaml#/definitions/flag + description: Defined when using BE SoC and device uses BE register read/write + +unevaluatedProperties: false + +required: + - reg + - reg-names + - interrupts + - interrupt-names + +examples: + - | # BRCMSTB SoC: SPI Master (MSPI+BSPI) for SPI-NOR access + spi@f03e3400 { + compatible = "brcm,spi-brcmstb-qspi", "brcm,spi-bcm-qspi"; + reg = <0xf03e3400 0x188>, <0xf03e3200 0x50>, <0xf03e0920 0x4>; + reg-names = "mspi", "bspi", "cs_reg"; + interrupts = <0x5>, <0x6>, <0x1>, <0x2>, <0x3>, <0x4>, <0x0>; + interrupt-parent = <&gic>; + interrupt-names = "mspi_done", + "mspi_halted", + "spi_lr_fullness_reached", + "spi_lr_session_aborted", + "spi_lr_impatient", + "spi_lr_session_done", + "spi_lr_overread"; + clocks = <&hif_spi>; + #address-cells = <0x1>; + #size-cells = <0x0>; + + flash@0 { + #size-cells = <0x2>; + #address-cells = <0x2>; + compatible = "m25p80"; + reg = <0x0>; + spi-max-frequency = <0x2625a00>; + spi-cpol; + spi-cpha; + }; + }; + - | # BRCMSTB SoC: MSPI master for any SPI device + spi@f0416000 { + clocks = <&upg_fixed>; + compatible = "brcm,spi-brcmstb-mspi", "brcm,spi-bcm-qspi"; + reg = <0xf0416000 0x180>; + reg-names = "mspi"; + interrupts = <0x14>; + interrupt-parent = <&irq0_aon_intc>; + interrupt-names = "mspi_done"; + #address-cells = <1>; + #size-cells = <0>; + }; + - | # iProc SoC + #include + #include + + spi@18027200 { + compatible = "brcm,spi-nsp-qspi", "brcm,spi-bcm-qspi"; + reg = <0x18027200 0x184>, + <0x18027000 0x124>, + <0x1811c408 0x004>, + <0x180273a0 0x01c>; + reg-names = "mspi", "bspi", "intr_regs", "intr_status_reg"; + interrupts = , + , + , + , + , + , + ; + interrupt-names = "mspi_done", + "mspi_halted", + "spi_lr_fullness_reached", + "spi_lr_session_aborted", + "spi_lr_impatient", + "spi_lr_session_done"; + clocks = <&iprocmed>; + num-cs = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + - | # NS2 SoC + #include + #include + + spi@66470200 { + compatible = "brcm,spi-ns2-qspi", "brcm,spi-bcm-qspi"; + reg = <0x66470200 0x184>, + <0x66470000 0x124>, + <0x67017408 0x004>, + <0x664703a0 0x01c>; + reg-names = "mspi", "bspi", "intr_regs", "intr_status_reg"; + interrupts = ; + interrupt-names = "spi_l1_intr"; + clocks = <&iprocmed>; + num-cs = <2>; + #address-cells = <1>; + #size-cells = <0>; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "m25p80"; + reg = <0x0>; + spi-max-frequency = <12500000>; + spi-cpol; + spi-cpha; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 206305cc869b5b..ba03e6c0b42c7b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3689,7 +3689,7 @@ BROADCOM SPI DRIVER M: Kamal Dasu M: bcm-kernel-feedback-list@broadcom.com S: Maintained -F: Documentation/devicetree/bindings/spi/brcm,spi-bcm-qspi.txt +F: Documentation/devicetree/bindings/spi/brcm,spi-bcm-qspi.yaml F: drivers/spi/spi-bcm-qspi.* F: drivers/spi/spi-brcmstb-qspi.c F: drivers/spi/spi-iproc-qspi.c From 3a1634daf8cbf7d1e76b120fea9665325557be8c Mon Sep 17 00:00:00 2001 From: Shivamurthy Shastri Date: Mon, 19 Apr 2021 20:40:15 +0000 Subject: [PATCH 107/113] spidev: Add Micron SPI NOR Authenta device compatible Add compatible string for Micron SPI NOR Authenta device. Signed-off-by: Shivamurthy Shastri Link: https://lore.kernel.org/r/20210419204015.1769-1-sshivamurthy@micron.com Signed-off-by: Mark Brown --- drivers/spi/spidev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 8cb4d923aeaab3..f56e0e975a4691 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -683,6 +683,7 @@ static const struct of_device_id spidev_dt_ids[] = { { .compatible = "dh,dhcom-board" }, { .compatible = "menlo,m53cpld" }, { .compatible = "cisco,spi-petra" }, + { .compatible = "micron,spi-authenta" }, {}, }; MODULE_DEVICE_TABLE(of, spidev_dt_ids); From 31ed8ebc7a27c1937184b956727bf71d4adc7df3 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Apr 2021 19:40:40 +0300 Subject: [PATCH 108/113] spi: Make error handling of gpiod_count() call cleaner Each time we call spi_get_gpio_descs() the num_chipselect is overwritten either by new value or by the old one. This is an extra operation in case gpiod_count() returns an error. Besides that it slashes the error handling of gpiod_count(). Refactor the code to make error handling of gpiod_count() call cleaner. Note, that gpiod_count() never returns 0, take this into account as well. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20210420164040.40055-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index cc6d43d7895f02..06db1316923108 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2551,13 +2551,14 @@ static int spi_get_gpio_descs(struct spi_controller *ctlr) unsigned int num_cs_gpios = 0; nb = gpiod_count(dev, "cs"); - ctlr->num_chipselect = max_t(int, nb, ctlr->num_chipselect); - - /* No GPIOs at all is fine, else return the error */ - if (nb == 0 || nb == -ENOENT) - return 0; - else if (nb < 0) + if (nb < 0) { + /* No GPIOs at all is fine, else return the error */ + if (nb == -ENOENT) + return 0; return nb; + } + + ctlr->num_chipselect = max_t(int, nb, ctlr->num_chipselect); cs = devm_kcalloc(dev, ctlr->num_chipselect, sizeof(*cs), GFP_KERNEL); From 24b5515aa3ac075880be776bf36553ff7f9712c7 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 20 Apr 2021 21:46:13 +0200 Subject: [PATCH 109/113] spi: fsi: add a missing of_node_put 'for_each_available_child_of_node' performs an of_node_get on each iteration, so a return from the middle of the loop requires an of_node_put. Fixes: bbb6b2f9865b ("spi: Add FSI-attached SPI controller driver") Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/504e431b900341249d331b868d90312cf41f415a.1618947919.git.christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- drivers/spi/spi-fsi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c index de359718e816f6..87f8829c399521 100644 --- a/drivers/spi/spi-fsi.c +++ b/drivers/spi/spi-fsi.c @@ -566,8 +566,10 @@ static int fsi_spi_probe(struct device *dev) continue; ctlr = spi_alloc_master(dev, sizeof(*ctx)); - if (!ctlr) + if (!ctlr) { + of_node_put(np); break; + } ctlr->dev.of_node = np; ctlr->num_chipselect = of_get_available_child_count(np) ?: 1; From bc2e9578baed90f36abe6bb922b9598a327b0555 Mon Sep 17 00:00:00 2001 From: Quanyang Wang Date: Thu, 22 Apr 2021 18:26:04 +0800 Subject: [PATCH 110/113] spi: tools: make a symbolic link to the header file spi.h The header file spi.h in include/uapi/linux/spi is needed for spidev.h, so we also need make a symbolic link to it to eliminate the error message as below: In file included from spidev_test.c:24: include/linux/spi/spidev.h:28:10: fatal error: linux/spi/spi.h: No such file or directory 28 | #include | ^~~~~~~~~~~~~~~~~ compilation terminated. Fixes: f7005142dace ("spi: uapi: unify SPI modes into a single spi.h") Signed-off-by: Quanyang Wang Link: https://lore.kernel.org/r/20210422102604.3034217-1-quanyang.wang@windriver.com Signed-off-by: Mark Brown --- tools/spi/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/spi/Makefile b/tools/spi/Makefile index ada881afb489a5..0aa6dbd31fb8d3 100644 --- a/tools/spi/Makefile +++ b/tools/spi/Makefile @@ -25,11 +25,12 @@ include $(srctree)/tools/build/Makefile.include # # We need the following to be outside of kernel tree # -$(OUTPUT)include/linux/spi/spidev.h: ../../include/uapi/linux/spi/spidev.h +$(OUTPUT)include/linux/spi: ../../include/uapi/linux/spi mkdir -p $(OUTPUT)include/linux/spi 2>&1 || true ln -sf $(CURDIR)/../../include/uapi/linux/spi/spidev.h $@ + ln -sf $(CURDIR)/../../include/uapi/linux/spi/spi.h $@ -prepare: $(OUTPUT)include/linux/spi/spidev.h +prepare: $(OUTPUT)include/linux/spi # # spidev_test From 14ef64ebdc2a4564893022780907747567452f6c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 22 Apr 2021 15:38:57 +0200 Subject: [PATCH 111/113] spi: stm32-qspi: fix debug format string Printing size_t needs a special %zx format modifier to avoid a warning like: drivers/spi/spi-stm32-qspi.c:481:41: note: format string is defined here 481 | dev_dbg(qspi->dev, "%s len = 0x%x offs = 0x%llx buf = 0x%p\n", __func__, len, offs, buf); Patrice already tried to fix this, but picked %lx instead of %zx, which fixed some architectures but broke others in the same way. Using %zx works everywhere. Fixes: 18674dee3cd6 ("spi: stm32-qspi: Add dirmap support") Fixes: 1b8a7d4282c0 ("spi: stm32-qspi: Fix compilation warning in ARM64") Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20210422134955.1988316-1-arnd@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-stm32-qspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c index 02691c1603d943..7e640ccc7e7742 100644 --- a/drivers/spi/spi-stm32-qspi.c +++ b/drivers/spi/spi-stm32-qspi.c @@ -478,7 +478,7 @@ static ssize_t stm32_qspi_dirmap_read(struct spi_mem_dirmap_desc *desc, * all needed transfer information into struct spi_mem_op */ memcpy(&op, &desc->info.op_tmpl, sizeof(struct spi_mem_op)); - dev_dbg(qspi->dev, "%s len = 0x%lx offs = 0x%llx buf = 0x%p\n", __func__, len, offs, buf); + dev_dbg(qspi->dev, "%s len = 0x%zx offs = 0x%llx buf = 0x%p\n", __func__, len, offs, buf); op.data.nbytes = len; op.addr.val = desc->info.offset + offs; From 9ec2a73f0b09f5a5070a0092f08b1531b2cb0d8d Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Fri, 12 Mar 2021 11:10:38 +0530 Subject: [PATCH 112/113] spi: Convert Freescale QSPI binding to json schema Convert the Freescale QSPI binding to DT schema format using json-schema. Signed-off-by: Kuldeep Singh Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20210312054038.3586706-1-kuldeep.singh@nxp.com Signed-off-by: Mark Brown --- .../bindings/spi/fsl,spi-fsl-qspi.yaml | 96 +++++++++++++++++++ .../devicetree/bindings/spi/spi-fsl-qspi.txt | 66 ------------- MAINTAINERS | 1 + 3 files changed, 97 insertions(+), 66 deletions(-) create mode 100644 Documentation/devicetree/bindings/spi/fsl,spi-fsl-qspi.yaml delete mode 100644 Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt diff --git a/Documentation/devicetree/bindings/spi/fsl,spi-fsl-qspi.yaml b/Documentation/devicetree/bindings/spi/fsl,spi-fsl-qspi.yaml new file mode 100644 index 00000000000000..e586445584124b --- /dev/null +++ b/Documentation/devicetree/bindings/spi/fsl,spi-fsl-qspi.yaml @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/fsl,spi-fsl-qspi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale Quad Serial Peripheral Interface (QuadSPI) + +maintainers: + - Han Xu + +allOf: + - $ref: "spi-controller.yaml#" + +properties: + compatible: + oneOf: + - enum: + - fsl,vf610-qspi + - fsl,imx6sx-qspi + - fsl,imx7d-qspi + - fsl,imx6ul-qspi + - fsl,ls1021a-qspi + - fsl,ls2080a-qspi + - items: + - enum: + - fsl,ls1043a-qspi + - const: fsl,ls1021a-qspi + - items: + - enum: + - fsl,imx8mq-qspi + - const: fsl,imx7d-qspi + + reg: + items: + - description: registers + - description: memory mapping + + reg-names: + items: + - const: QuadSPI + - const: QuadSPI-memory + + interrupts: + maxItems: 1 + + clocks: + items: + - description: SoC SPI qspi_en clock + - description: SoC SPI qspi clock + + clock-names: + items: + - const: qspi_en + - const: qspi + +required: + - compatible + - reg + - reg-names + - interrupts + - clocks + - clock-names + +unevaluatedProperties: false + +examples: + - | + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + spi@1550000 { + compatible = "fsl,ls1021a-qspi"; + reg = <0x0 0x1550000 0x0 0x100000>, + <0x0 0x40000000 0x0 0x10000000>; + reg-names = "QuadSPI", "QuadSPI-memory"; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL QORIQ_CLK_PLL_DIV(2)>, + <&clockgen QORIQ_CLK_PLATFORM_PLL QORIQ_CLK_PLL_DIV(2)>; + clock-names = "qspi_en", "qspi"; + + flash@0 { + compatible = "jedec,spi-nor"; + spi-max-frequency = <50000000>; + reg = <0>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <4>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt deleted file mode 100644 index 69dc5d57b1efbe..00000000000000 --- a/Documentation/devicetree/bindings/spi/spi-fsl-qspi.txt +++ /dev/null @@ -1,66 +0,0 @@ -* Freescale Quad Serial Peripheral Interface(QuadSPI) - -Required properties: - - compatible : Should be "fsl,vf610-qspi", "fsl,imx6sx-qspi", - "fsl,imx7d-qspi", "fsl,imx6ul-qspi", - "fsl,ls1021a-qspi", "fsl,ls2080a-qspi" - or - "fsl,ls1043a-qspi" followed by "fsl,ls1021a-qspi" - - reg : the first contains the register location and length, - the second contains the memory mapping address and length - - reg-names: Should contain the reg names "QuadSPI" and "QuadSPI-memory" - - interrupts : Should contain the interrupt for the device - - clocks : The clocks needed by the QuadSPI controller - - clock-names : Should contain the name of the clocks: "qspi_en" and "qspi". - -Required SPI slave node properties: - - reg: There are two buses (A and B) with two chip selects each. - This encodes to which bus and CS the flash is connected: - <0>: Bus A, CS 0 - <1>: Bus A, CS 1 - <2>: Bus B, CS 0 - <3>: Bus B, CS 1 - -Example: - -qspi0: quadspi@40044000 { - compatible = "fsl,vf610-qspi"; - reg = <0x40044000 0x1000>, <0x20000000 0x10000000>; - reg-names = "QuadSPI", "QuadSPI-memory"; - interrupts = <0 24 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks VF610_CLK_QSPI0_EN>, - <&clks VF610_CLK_QSPI0>; - clock-names = "qspi_en", "qspi"; - - flash0: s25fl128s@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "spansion,s25fl128s", "jedec,spi-nor"; - spi-max-frequency = <50000000>; - reg = <0>; - }; -}; - -Example showing the usage of two SPI NOR devices on bus A: - -&qspi2 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_qspi2>; - status = "okay"; - - flash0: n25q256a@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "micron,n25q256a", "jedec,spi-nor"; - spi-max-frequency = <29000000>; - reg = <0>; - }; - - flash1: n25q256a@1 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "micron,n25q256a", "jedec,spi-nor"; - spi-max-frequency = <29000000>; - reg = <1>; - }; -}; diff --git a/MAINTAINERS b/MAINTAINERS index ba03e6c0b42c7b..1c98272079492b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7161,6 +7161,7 @@ FREESCALE QUAD SPI DRIVER M: Han Xu L: linux-spi@vger.kernel.org S: Maintained +F: Documentation/devicetree/bindings/spi/fsl,spi-fsl-qspi.yaml F: drivers/spi/spi-fsl-qspi.c FREESCALE QUICC ENGINE LIBRARY From 86527bcbc88922ea40df05d28189ee15489d2cf1 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Apr 2021 16:18:46 +0300 Subject: [PATCH 113/113] spi: Rename enable1 to activate in spi_set_cs() The enable1 is confusing name. Change it to clearly show what is the intention behind it. No functional changes. Fixes: 25093bdeb6bc ("spi: implement SW control for CS times") Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20210420131846.75983-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 06db1316923108..ba425b9c77007a 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -788,7 +788,7 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) static void spi_set_cs(struct spi_device *spi, bool enable, bool force) { - bool enable1 = enable; + bool activate = enable; /* * Avoid calling into the driver (or doing delays) if the chip select @@ -803,7 +803,7 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force) if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) || !spi->controller->set_cs_timing) { - if (enable1) + if (activate) spi_delay_exec(&spi->controller->cs_setup, NULL); else spi_delay_exec(&spi->controller->cs_hold, NULL); @@ -816,8 +816,7 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force) if (!(spi->mode & SPI_NO_CS)) { if (spi->cs_gpiod) /* polarity handled by gpiolib */ - gpiod_set_value_cansleep(spi->cs_gpiod, - enable1); + gpiod_set_value_cansleep(spi->cs_gpiod, activate); else /* * invert the enable line, as active low is @@ -835,7 +834,7 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force) if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) || !spi->controller->set_cs_timing) { - if (!enable1) + if (!activate) spi_delay_exec(&spi->controller->cs_inactive, NULL); } }