From ffef4123043c5bb29e61052a41e577ae1ee6837a Mon Sep 17 00:00:00 2001 From: Antoniu Miclaus Date: Fri, 6 Feb 2026 18:07:13 +0200 Subject: [PATCH 001/115] spi: allow ancillary devices to share parent's chip selects When registering an ancillary SPI device, the current code flags a chip select conflict with the parent device. This happens because the ancillary device intentionally uses one of the parent's chip selects, but __spi_add_device() checks against all existing devices including the parent. Allow this by passing the parent device pointer to __spi_add_device() and skipping the conflict check when the existing device is the parent. Signed-off-by: Antoniu Miclaus Reviewed-by: David Lechner Link: https://patch.msgid.link/bcb1eb34fc5e86fd5dbb4472ad1d3ea3cf3e9779.1770393792.git.antoniu.miclaus@analog.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 61f7bde8c7fb..8fbed4754de4 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -641,12 +641,26 @@ static inline int spi_dev_check_cs(struct device *dev, return 0; } +struct spi_dev_check_info { + struct spi_device *new_spi; + struct spi_device *parent; /* set for ancillary devices */ +}; + static int spi_dev_check(struct device *dev, void *data) { struct spi_device *spi = to_spi_device(dev); - struct spi_device *new_spi = data; + struct spi_dev_check_info *info = data; + struct spi_device *new_spi = info->new_spi; int status, idx; + /* + * When registering an ancillary device, skip checking against the + * parent device since the ancillary is intentionally using one of + * the parent's chip selects. + */ + if (info->parent && spi == info->parent) + return 0; + if (spi->controller == new_spi->controller) { for (idx = 0; idx < spi->num_chipselect; idx++) { status = spi_dev_check_cs(dev, spi, idx, new_spi, 0); @@ -663,10 +677,11 @@ static void spi_cleanup(struct spi_device *spi) spi->controller->cleanup(spi); } -static int __spi_add_device(struct spi_device *spi) +static int __spi_add_device(struct spi_device *spi, struct spi_device *parent) { struct spi_controller *ctlr = spi->controller; struct device *dev = ctlr->dev.parent; + struct spi_dev_check_info check_info; int status, idx; u8 cs; @@ -710,7 +725,9 @@ static int __spi_add_device(struct spi_device *spi) * chipselect **BEFORE** we call setup(), else we'll trash * its configuration. */ - status = bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check); + check_info.new_spi = spi; + check_info.parent = parent; + status = bus_for_each_dev(&spi_bus_type, NULL, &check_info, spi_dev_check); if (status) return status; @@ -772,7 +789,7 @@ int spi_add_device(struct spi_device *spi) spi_dev_set_name(spi); mutex_lock(&ctlr->add_lock); - status = __spi_add_device(spi); + status = __spi_add_device(spi, NULL); mutex_unlock(&ctlr->add_lock); return status; } @@ -2715,8 +2732,8 @@ struct spi_device *spi_new_ancillary_device(struct spi_device *spi, WARN_ON(!mutex_is_locked(&ctlr->add_lock)); - /* Register the new device */ - rc = __spi_add_device(ancillary); + /* Register the new device, passing the parent to skip CS conflict check */ + rc = __spi_add_device(ancillary, spi); if (rc) { dev_err(&spi->dev, "failed to register ancillary device\n"); goto err_out; From 20a88c156f37634fdd88b746fa34e3622f567130 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 23 Feb 2026 10:07:17 +0000 Subject: [PATCH 002/115] spi: cs42l43: Don't support sidecar properties on device tree systems On some systems the cs42l43 has amplifiers attached to its SPI controller that are not properly defined in ACPI. However, this exists to provide compatibility with existing Windows ACPI. On device tree systems this functionality should never be used, there is no reason not to specify the amplifiers properly through device tree. Make this more clear by only allowing the "sidecar" functionality to be used on non-DT systems. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260223100717.4011114-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- drivers/spi/spi-cs42l43.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-cs42l43.c b/drivers/spi/spi-cs42l43.c index a4a650c8d740..68f208ef1e01 100644 --- a/drivers/spi/spi-cs42l43.c +++ b/drivers/spi/spi-cs42l43.c @@ -367,10 +367,10 @@ static int cs42l43_spi_probe(struct platform_device *pdev) ret = devm_add_action_or_reset(priv->dev, cs42l43_release_of_node, fwnode); if (ret) return ret; + } else { + fwnode_property_read_u32(xu_fwnode, "01fa-sidecar-instances", &nsidecars); } - fwnode_property_read_u32(xu_fwnode, "01fa-sidecar-instances", &nsidecars); - /* * Depending on the value of nsidecars we either create a software node * or assign an fwnode. We don't want software node to be attached to From 837f6691d5f39ea6453e4489dded40fb17755c60 Mon Sep 17 00:00:00 2001 From: Alain Volmat Date: Thu, 12 Feb 2026 12:49:10 +0100 Subject: [PATCH 003/115] spi: stm32: fix rx DMA request error handling Avoid trying to release the RX DMA channel when an error occurs during RX dma_request_chan() call. Instead, jump directly to release the TX channel, if applicable. Reported-by: Dan Carpenter Closes: https://lore.kernel.org/linux-spi/aYXvY6NH7OlZ-OAF@stanley.mountain/T/#u Signed-off-by: Alain Volmat Link: https://patch.msgid.link/20260212-spi-stm32-fix-dma-rx-release-v1-1-53a37c31626b@foss.st.com Signed-off-by: Mark Brown --- drivers/spi/spi-stm32.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index b99de8c4cc99..c9442326782c 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -2502,7 +2502,7 @@ static int stm32_spi_probe(struct platform_device *pdev) spi->dma_rx = NULL; } else { dev_err_probe(&pdev->dev, ret, "failed to request rx dma channel\n"); - goto err_dma_release; + goto err_dma_tx_release; } } else { ctrl->dma_rx = spi->dma_rx; @@ -2571,11 +2571,11 @@ static int stm32_spi_probe(struct platform_device *pdev) if (spi->sram_pool) gen_pool_free(spi->sram_pool, (unsigned long)spi->sram_rx_buf, spi->sram_rx_buf_size); -err_dma_release: - if (spi->dma_tx) - dma_release_channel(spi->dma_tx); if (spi->dma_rx) dma_release_channel(spi->dma_rx); +err_dma_tx_release: + if (spi->dma_tx) + dma_release_channel(spi->dma_tx); err_clk_disable: clk_disable_unprepare(spi->clk); From 52531750d39b94803e089dda95e43925730c03bd Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Fri, 13 Feb 2026 09:19:11 +0100 Subject: [PATCH 004/115] spi: stm32-ospi: Remove exec_op() callback debug log Since commit ad4488845193 ("spi: spi-mem: Introduce a default ->exec_op() debug log") a common debug log is available in spi-mem, so remove the one from spi-stm32-ospi driver. Signed-off-by: Patrice Chotard Link: https://patch.msgid.link/20260213-upstream_ospi_remove_exec_op_debug_log-v1-1-164f17515fd0@foss.st.com Signed-off-by: Mark Brown --- drivers/spi/spi-stm32-ospi.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/spi/spi-stm32-ospi.c b/drivers/spi/spi-stm32-ospi.c index c98afe02a1b6..acf2d182e8b1 100644 --- a/drivers/spi/spi-stm32-ospi.c +++ b/drivers/spi/spi-stm32-ospi.c @@ -469,11 +469,6 @@ static int stm32_ospi_send(struct spi_device *spi, const struct spi_mem_op *op) int timeout, err = 0, err_poll_status = 0; u8 cs = spi->chip_select[ffs(spi->cs_index_mask) - 1]; - dev_dbg(ospi->dev, "cmd:%#x mode:%d.%d.%d.%d addr:%#llx len:%#x\n", - op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, - op->dummy.buswidth, op->data.buswidth, - op->addr.val, op->data.nbytes); - cr = readl_relaxed(ospi->regs_base + OSPI_CR); cr &= ~CR_CSSEL; cr |= FIELD_PREP(CR_CSSEL, cs); From 5e897a498a6b45145350e9de5e4753e9eee7d4f6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 16 Feb 2026 09:58:17 +0100 Subject: [PATCH 005/115] spi: stm32: Use NULL instead of 0 for pointer Pointers should use NULL instead of explicit '0', as pointed out by sparse: spi-stm32.c:1659:65: warning: Using plain integer as NULL pointer Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260216085816.69888-2-krzysztof.kozlowski@oss.qualcomm.com Signed-off-by: Mark Brown --- drivers/spi/spi-stm32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index c9442326782c..f4a8a3fb1888 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -1656,7 +1656,7 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, ret = stm32_spi_prepare_rx_dma_mdma_chaining(spi, xfer, &rx_dma_conf, &rx_dma_desc, &rx_mdma_desc); if (ret) { /* RX DMA MDMA chaining not possible, fallback to DMA only */ - rx_dma_conf.peripheral_config = 0; + rx_dma_conf.peripheral_config = NULL; rx_dma_desc = NULL; } } From 4d28f38f64ef69ab27839069ef3346c3c878d137 Mon Sep 17 00:00:00 2001 From: Cosmin Tanislav Date: Wed, 28 Jan 2026 23:51:30 +0200 Subject: [PATCH 006/115] spi: dt-bindings: renesas,rzv2h-rspi: allow multiple DMAs All supported SoCs have multiple DMA controllers that can be used with the RSPI peripheral. The current bindings only allow a single pair of RX and TX DMAs. The DMA core allows specifying multiple DMAs with the same name, and it will pick the first available one. There is an exception in the base dt-schema rules specifically for allowing this behavior (dtschema/schemas/dma/dma.yaml). dma-names: anyOf: - uniqueItems: true - items: # Hack around Renesas bindings which repeat entries to support # multiple possible DMA providers enum: [rx, tx] Allow multiple DMAs to have the same name and only restrict the possible names of the DMA channels, not their count. For RZ/T2H and RZ/N2H SoCs, limit the number of DMA channels to 6, as they have 3 DMA controllers. For RZ/V2H and RZ/V2N SoCs, limit the number of DMA channels to 10, as they have 5 DMA controllers. Signed-off-by: Cosmin Tanislav Acked-by: Conor Dooley Link: https://patch.msgid.link/20260128215132.1353381-2-cosmin-gabriel.tanislav.xa@renesas.com Signed-off-by: Mark Brown --- .../bindings/spi/renesas,rzv2h-rspi.yaml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml b/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml index a588b112e11e..cf8b733b766d 100644 --- a/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml +++ b/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml @@ -58,12 +58,16 @@ properties: - const: tresetn dmas: - maxItems: 2 + minItems: 2 + maxItems: 10 dma-names: + minItems: 2 + maxItems: 10 items: - - const: rx - - const: tx + enum: + - rx + - tx power-domains: maxItems: 1 @@ -121,6 +125,12 @@ allOf: resets: false reset-names: false + dmas: + maxItems: 6 + + dma-names: + maxItems: 6 + unevaluatedProperties: false examples: From 6f7e9b11549dc726270a7e8539201d4270f15803 Mon Sep 17 00:00:00 2001 From: Antoni Pokusinski Date: Sat, 14 Feb 2026 22:28:00 +0100 Subject: [PATCH 007/115] spi: omap2-mcspi: add support for 3-wire transfers Update omap_mcspi_setup_transfer() so that the driver supports communication over a single data line for 3-wire SPI devices. Signed-off-by: Antoni Pokusinski Link: https://patch.msgid.link/20260214212800.262461-1-apokusinski01@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 2207e05c9d06..a3468e47e77d 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -942,10 +942,16 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, l = mcspi_cached_chconf0(spi); - /* standard 4-wire host mode: SCK, MOSI/out, MISO/in, nCS - * REVISIT: this controller could support SPI_3WIRE mode. - */ - if (mcspi->pin_dir == MCSPI_PINDIR_D0_IN_D1_OUT) { + if (spi->mode & SPI_3WIRE) { + if (t && !t->tx_buf) { + l &= ~OMAP2_MCSPI_CHCONF_IS; + l |= OMAP2_MCSPI_CHCONF_DPE0; + } else if (t && !t->rx_buf) { + l |= OMAP2_MCSPI_CHCONF_IS; + l &= ~OMAP2_MCSPI_CHCONF_DPE0; + } + l |= OMAP2_MCSPI_CHCONF_DPE1; + } else if (mcspi->pin_dir == MCSPI_PINDIR_D0_IN_D1_OUT) { l &= ~OMAP2_MCSPI_CHCONF_IS; l &= ~OMAP2_MCSPI_CHCONF_DPE1; l |= OMAP2_MCSPI_CHCONF_DPE0; @@ -1178,6 +1184,7 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr, omap2_mcspi_set_cs(spi, spi->mode & SPI_CS_HIGH); if (par_override || + (spi->mode & SPI_3WIRE) || (t->speed_hz != spi->max_speed_hz) || (t->bits_per_word != spi->bits_per_word)) { par_override = 1; @@ -1484,7 +1491,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) return -ENOMEM; /* the spi->mode bits understood by this driver: */ - ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_3WIRE; ctlr->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); ctlr->setup = omap2_mcspi_setup; ctlr->auto_runtime_pm = true; From fed6e5084894373d76270cad4a32eb6479ad8247 Mon Sep 17 00:00:00 2001 From: Pei Xiao Date: Fri, 20 Feb 2026 10:44:25 +0800 Subject: [PATCH 008/115] spi: atcspi200: Remove redundant assignment to .owner The coccicheck tool reports the following warning for this driver: ./spi-atcspi200.c:670:3-8: No need to set .owner here. The core will do it. The manual assignment of .owner = THIS_MODULE; in the platform_driver struct is redundant. The platform_driver_register() function, which is called to register the driver, is a macro that automatically sets the driver's owner to THIS_MODULE. The driver core handles this assignment internally, making the explicit initialization in the struct definition unnecessary. Remove the unnecessary line. Signed-off-by: Pei Xiao Link: https://patch.msgid.link/tencent_65C9C09CBD2B68C400F7145521A4B217E606@qq.com Signed-off-by: Mark Brown --- drivers/spi/spi-atcspi200.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/spi/spi-atcspi200.c b/drivers/spi/spi-atcspi200.c index 60a37ff5c6f5..2075058387f3 100644 --- a/drivers/spi/spi-atcspi200.c +++ b/drivers/spi/spi-atcspi200.c @@ -667,7 +667,6 @@ static struct platform_driver atcspi_driver = { .probe = atcspi_probe, .driver = { .name = "atcspi200", - .owner = THIS_MODULE, .of_match_table = atcspi_of_match, .pm = pm_sleep_ptr(&atcspi_pm_ops) } From 507a071d9868cb60e4e76f8a06fc8eb014f59ae4 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 23 Feb 2026 16:30:54 +0100 Subject: [PATCH 009/115] spi: pxa2xx: use min() instead of min_t() min_t(int, a, b) casts an 'u32' to 'int'. This might lead to the cases when big number is wrongly chosen. On the other hand, the SPI transfer speed rate is unsigned and driver uses signed type for an unknown reason. Change the type of the SPI transfer speed to be unsigned and convert to use min() instead of min_t(). Signed-off-by: Andy Shevchenko Reviewed-by: David Laight Link: https://patch.msgid.link/20260223153117.2838840-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index f7881a31e4cc..6291d7c2e06f 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -796,7 +796,7 @@ static irqreturn_t ssp_int(int irq, void *dev_id) * The function calculates parameters for all cases and chooses the one closest * to the asked baud rate. */ -static unsigned int quark_x1000_get_clk_div(int rate, u32 *dds) +static unsigned int quark_x1000_get_clk_div(u32 rate, u32 *dds) { unsigned long xtal = 200000000; unsigned long fref = xtal / 2; /* mandatory division by 2, @@ -885,12 +885,12 @@ static unsigned int quark_x1000_get_clk_div(int rate, u32 *dds) return q - 1; } -static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate) +static unsigned int ssp_get_clk_div(struct driver_data *drv_data, u32 rate) { - unsigned long ssp_clk = drv_data->controller->max_speed_hz; + u32 ssp_clk = drv_data->controller->max_speed_hz; const struct ssp_device *ssp = drv_data->ssp; - rate = min_t(int, ssp_clk, rate); + rate = min(ssp_clk, rate); /* * Calculate the divisor for the SCR (Serial Clock Rate), avoiding @@ -902,8 +902,7 @@ static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate) return (DIV_ROUND_UP(ssp_clk, rate) - 1) & 0xfff; } -static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data, - int rate) +static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data, u32 rate) { struct chip_data *chip = spi_get_ctldata(drv_data->controller->cur_msg->spi); From 7c12f6ead4672cb08b74e6f6115eb04dca8ccfa4 Mon Sep 17 00:00:00 2001 From: Vishwaroop A Date: Tue, 24 Feb 2026 09:24:52 +0000 Subject: [PATCH 010/115] spi: tegra210-quad: Add runtime autosuspend support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using Tegra234, it was found that it takes about 10us to disable clocks and 20us to enable clocks, adding about 30us overhead per operation. For a 4MB firmware update with 16,384 page programs, this results in ~491ms total overhead (12% impact). With Tegra234, flash operations were observed to occur in bursts with 50-200μs gaps between page programs. Testing on Tegra234 with various operation patterns shows 500ms delay provides optimal balance, and for longer operations (>500ms), the overhead is negligible. Therefore, update the driver to use pm-runtime autosuspend with the default timeout of 500ms to reduce the clock gating overhead during consecutive QSPI transfers. Signed-off-by: Vishwaroop A Link: https://patch.msgid.link/20260224092452.1482800-1-va@nvidia.com Signed-off-by: Mark Brown --- drivers/spi/spi-tegra210-quad.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c index 7ea5aa993596..7fac695b5142 100644 --- a/drivers/spi/spi-tegra210-quad.c +++ b/drivers/spi/spi-tegra210-quad.c @@ -1000,7 +1000,8 @@ static int tegra_qspi_setup(struct spi_device *spi) spin_unlock_irqrestore(&tqspi->lock, flags); - pm_runtime_put(tqspi->dev); + pm_runtime_mark_last_busy(tqspi->dev); + pm_runtime_put_autosuspend(tqspi->dev); return 0; } @@ -1765,6 +1766,14 @@ static int tegra_qspi_probe(struct platform_device *pdev) init_completion(&tqspi->rx_dma_complete); init_completion(&tqspi->xfer_completion); + /* + * Set autosuspend delay to 500ms. Testing shows this value eliminates + * suspend/resume overhead during burst operations while allowing quick + * suspension during idle. For longer operations, the overhead is negligible. + */ + pm_runtime_set_autosuspend_delay(&pdev->dev, 500); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(&pdev->dev); ret = pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) { @@ -1781,7 +1790,8 @@ static int tegra_qspi_probe(struct platform_device *pdev) tqspi->spi_cs_timing2 = tegra_qspi_readl(tqspi, QSPI_CS_TIMING2); tqspi->def_command2_reg = tegra_qspi_readl(tqspi, QSPI_COMMAND2); - pm_runtime_put(&pdev->dev); + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); ret = request_threaded_irq(tqspi->irq, NULL, tegra_qspi_isr_thread, IRQF_ONESHOT, @@ -1802,6 +1812,7 @@ static int tegra_qspi_probe(struct platform_device *pdev) exit_free_irq: free_irq(qspi_irq, tqspi); exit_pm_disable: + pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_force_suspend(&pdev->dev); tegra_qspi_deinit_dma(tqspi); return ret; @@ -1814,6 +1825,7 @@ static void tegra_qspi_remove(struct platform_device *pdev) spi_unregister_controller(host); free_irq(tqspi->irq, tqspi); + pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_force_suspend(&pdev->dev); tegra_qspi_deinit_dma(tqspi); } @@ -1839,7 +1851,8 @@ static int __maybe_unused tegra_qspi_resume(struct device *dev) tegra_qspi_writel(tqspi, tqspi->command1_reg, QSPI_COMMAND1); tegra_qspi_writel(tqspi, tqspi->def_command2_reg, QSPI_COMMAND2); - pm_runtime_put(dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); return spi_controller_resume(host); } From e02902dd493bf9c9b05353c761737ac514ad7a5c Mon Sep 17 00:00:00 2001 From: Antoniu Miclaus Date: Mon, 23 Feb 2026 18:21:01 +0200 Subject: [PATCH 011/115] spi: add devm_spi_new_ancillary_device() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a devres-managed version of spi_new_ancillary_device() that automatically unregisters the ancillary SPI device when the parent device is removed. This follows the same devm_add_action_or_reset() pattern used by the other managed SPI functions (devm_spi_optimize_message, devm_spi_register_controller, etc.) and eliminates the need for drivers to open-code their own devm cleanup callbacks for ancillary devices. Acked-by: Nuno Sá Signed-off-by: Antoniu Miclaus Link: https://patch.msgid.link/20260223162110.156746-3-antoniu.miclaus@analog.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 40 ++++++++++++++++++++++++++++++++++++++++ include/linux/spi/spi.h | 1 + 2 files changed, 41 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 8fbed4754de4..26cc10aa7533 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2747,6 +2747,46 @@ struct spi_device *spi_new_ancillary_device(struct spi_device *spi, } EXPORT_SYMBOL_GPL(spi_new_ancillary_device); +static void devm_spi_unregister_device(void *spi) +{ + spi_unregister_device(spi); +} + +/** + * devm_spi_new_ancillary_device() - Register managed ancillary SPI device + * @spi: Pointer to the main SPI device registering the ancillary device + * @chip_select: Chip Select of the ancillary device + * + * Register an ancillary SPI device; for example some chips have a chip-select + * for normal device usage and another one for setup/firmware upload. + * + * This is the managed version of spi_new_ancillary_device(). The ancillary + * device will be unregistered automatically when the parent SPI device is + * unregistered. + * + * This may only be called from main SPI device's probe routine. + * + * Return: Pointer to new ancillary device on success; ERR_PTR on failure + */ +struct spi_device *devm_spi_new_ancillary_device(struct spi_device *spi, + u8 chip_select) +{ + struct spi_device *ancillary; + int ret; + + ancillary = spi_new_ancillary_device(spi, chip_select); + if (IS_ERR(ancillary)) + return ancillary; + + ret = devm_add_action_or_reset(&spi->dev, devm_spi_unregister_device, + ancillary); + if (ret) + return ERR_PTR(ret); + + return ancillary; +} +EXPORT_SYMBOL_GPL(devm_spi_new_ancillary_device); + #ifdef CONFIG_ACPI struct acpi_spi_lookup { struct spi_controller *ctlr; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index af7cfee7b8f6..1c9aab627583 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -387,6 +387,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) } extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 chip_select); +extern struct spi_device *devm_spi_new_ancillary_device(struct spi_device *spi, u8 chip_select); /* Use a define to avoid include chaining to get THIS_MODULE */ #define spi_register_driver(driver) \ From d3b693a13b39bce16e284e1c737874966b3a96de Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 28 Feb 2026 17:47:43 -0800 Subject: [PATCH 012/115] spi: spi-mem: clean up kernel-doc in spi-mem.h Eliminate all kernel-doc warnings in spi-mem.h: - add missing struct member descriptions - don't use "struct" for function descrptions Warning: include/linux/spi/spi-mem.h:202 struct member 'cmd' not described in 'spi_mem_op' Warning: include/linux/spi/spi-mem.h:202 struct member 'addr' not described in 'spi_mem_op' Warning: include/linux/spi/spi-mem.h:202 struct member 'dummy' not described in 'spi_mem_op' Warning: include/linux/spi/spi-mem.h:202 struct member 'data' not described in 'spi_mem_op' Warning: include/linux/spi/spi-mem.h:286 Incorrect use of kernel-doc format: * struct spi_mem_get_drvdata() - get driver private data attached to a SPI mem Warning: include/linux/spi/spi-mem.h:298 Incorrect use of kernel-doc format: * struct spi_controller_mem_ops - SPI memory operations Warning: include/linux/spi/spi-mem.h:362 expecting prototype for struct spi_mem_set_drvdata. Prototype was for struct spi_controller_mem_ops instead Signed-off-by: Randy Dunlap Link: https://patch.msgid.link/20260301014743.3133167-1-rdunlap@infradead.org Signed-off-by: Mark Brown --- include/linux/spi/spi-mem.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h index 5774e554c0f0..37f709784350 100644 --- a/include/linux/spi/spi-mem.h +++ b/include/linux/spi/spi-mem.h @@ -130,11 +130,13 @@ enum spi_mem_data_dir { /** * struct spi_mem_op - describes a SPI memory operation + * @cmd: the complete command * @cmd.nbytes: number of opcode bytes (only 1 or 2 are valid). The opcode is * sent MSB-first. * @cmd.buswidth: number of IO lines used to transmit the command * @cmd.opcode: operation opcode * @cmd.dtr: whether the command opcode should be sent in DTR mode or not + * @addr: the address attributes * @addr.nbytes: number of address bytes to send. Can be zero if the operation * does not need to send an address * @addr.buswidth: number of IO lines used to transmit the address cycles @@ -143,10 +145,12 @@ enum spi_mem_data_dir { * Note that only @addr.nbytes are taken into account in this * address value, so users should make sure the value fits in the * assigned number of bytes. + * @dummy: data for dummy operation * @dummy.nbytes: number of dummy bytes to send after an opcode or address. Can * be zero if the operation does not require dummy bytes * @dummy.buswidth: number of IO lanes used to transmit the dummy bytes * @dummy.dtr: whether the dummy bytes should be sent in DTR mode or not + * @data: the data attributes * @data.buswidth: number of IO lanes used to send/receive the data * @data.dtr: whether the data should be sent in DTR mode or not * @data.ecc: whether error correction is required or not @@ -273,7 +277,7 @@ struct spi_mem { }; /** - * struct spi_mem_set_drvdata() - attach driver private data to a SPI mem + * spi_mem_set_drvdata() - attach driver private data to a SPI mem * device * @mem: memory device * @data: data to attach to the memory device @@ -284,7 +288,7 @@ static inline void spi_mem_set_drvdata(struct spi_mem *mem, void *data) } /** - * struct spi_mem_get_drvdata() - get driver private data attached to a SPI mem + * spi_mem_get_drvdata() - get driver private data attached to a SPI mem * device * @mem: memory device * From f5d09914d473059e4e851c6a3bfa9f0e848c63e4 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Tue, 3 Mar 2026 16:41:50 +0000 Subject: [PATCH 013/115] spi: dt-bindings: mpfs-spi: permit resets CoreSPI, CoreQSPI and the hardened versions of them on mpfs and pic64gx have a reset pin. For the first two, usually this is wired to a common fabric reset not managed by software and for the latter two the platform firmware takes them out of reset on first-party boards (or those using modified versions of the vendor firmware), but not all boards may take this approach. Permit providing a reset in devicetree for Linux, or other devicetree-consuming software, to use. Signed-off-by: Conor Dooley Link: https://patch.msgid.link/20260303-deceiver-rack-82f2b89eac40@spud Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml b/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml index 636338d24bdf..b7d8acc924be 100644 --- a/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml +++ b/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml @@ -41,6 +41,9 @@ properties: clocks: maxItems: 1 + resets: + maxItems: 1 + microchip,apb-datawidth: description: APB bus data width in bits. $ref: /schemas/types.yaml#/definitions/uint32 From 96f06d055ca03d1dfb5830fd07ff6eadbd66264c Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Tue, 3 Mar 2026 16:41:52 +0000 Subject: [PATCH 014/115] spi: dt-bindings: mpfs-spi: remove clock-names This binding documented clock-names, but never bothered to document what the name should be, rendering the property useless to software. It's not a required property, so it can just be removed without harming any software that conjured up it's own name for the clock, as they could not rely on it being there to begin with. Signed-off-by: Conor Dooley Link: https://patch.msgid.link/20260303-spoils-snowbird-99f6e3a2dae3@spud Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml b/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml index b7d8acc924be..8ff50dfcf585 100644 --- a/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml +++ b/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml @@ -35,9 +35,6 @@ properties: interrupts: maxItems: 1 - clock-names: - maxItems: 1 - clocks: maxItems: 1 From 40f9bc646db5aa89fb85f2cda1e55a2bf9d6a30c Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Wed, 4 Mar 2026 20:47:19 +0800 Subject: [PATCH 015/115] spi: nxp-xspi: Use reinit_completion() for repeated operations The driver currently calls init_completion() during every spi_mem_op. Tchnically it may work, but it's not the recommended pattern. According to the kernel documentation: Calling init_completion() on the same completion object twice is most likely a bug as it re-initializes the queue to an empty queue and enqueued tasks could get "lost" - use reinit_completion() in that case, but be aware of other races. So moves the initial initialization to probe function and uses reinit_completion() for subsequent operations. Fixes: 29c8c00d9f9d ("spi: add driver for NXP XSPI controller") Reviewed-by: Haibo Chen Signed-off-by: Felix Gu Link: https://patch.msgid.link/20260304-spi-nxp-v2-1-cd7d7726a27e@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-nxp-xspi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-nxp-xspi.c b/drivers/spi/spi-nxp-xspi.c index 06fcdf22990b..385302a6e62f 100644 --- a/drivers/spi/spi-nxp-xspi.c +++ b/drivers/spi/spi-nxp-xspi.c @@ -958,7 +958,7 @@ static int nxp_xspi_do_op(struct nxp_xspi *xspi, const struct spi_mem_op *op) writel(reg, base + XSPI_RBCT); } - init_completion(&xspi->c); + reinit_completion(&xspi->c); /* Config the data address */ writel(op->addr.val + xspi->memmap_phy, base + XSPI_SFP_TG_SFAR); @@ -1273,6 +1273,7 @@ static int nxp_xspi_probe(struct platform_device *pdev) nxp_xspi_default_setup(xspi); + init_completion(&xspi->c); ret = devm_request_irq(dev, irq, nxp_xspi_irq_handler, 0, pdev->name, xspi); if (ret) From 68c8c93fdb0de7e528dc3dfb1d17eb0f652259b8 Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Wed, 4 Mar 2026 20:47:20 +0800 Subject: [PATCH 016/115] spi: nxp-fspi: Use reinit_completion() for repeated operations The driver currently calls init_completion() during every spi_mem_op. Tchnically it may work, but it's not the recommended pattern. According to the kernel documentation: Calling init_completion() on the same completion object twice is most likely a bug as it re-initializes the queue to an empty queue and enqueued tasks could get "lost" - use reinit_completion() in that case, but be aware of other races. So moves the initial initialization to probe function and uses reinit_completion() for subsequent operations. Fixes: a5356aef6a90 ("spi: spi-mem: Add driver for NXP FlexSPI controller") Signed-off-by: Felix Gu Reviewed-by: Haibo Chen Link: https://patch.msgid.link/20260304-spi-nxp-v2-2-cd7d7726a27e@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-nxp-fspi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index 320b3d93df57..1e36ae084dd8 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -996,7 +996,7 @@ static int nxp_fspi_do_op(struct nxp_fspi *f, const struct spi_mem_op *op) reg = reg | FSPI_IPRXFCR_CLR; fspi_writel(f, reg, base + FSPI_IPRXFCR); - init_completion(&f->c); + reinit_completion(&f->c); fspi_writel(f, op->addr.val, base + FSPI_IPCR0); /* @@ -1365,6 +1365,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) if (ret < 0) return dev_err_probe(dev, ret, "Failed to disable clock"); + init_completion(&f->c); ret = devm_request_irq(dev, irq, nxp_fspi_irq_handler, 0, pdev->name, f); if (ret) From 981b080a79724738882b0af1c5bb7ade30d94f24 Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Wed, 4 Mar 2026 20:47:21 +0800 Subject: [PATCH 017/115] spi: fsl-qspi: Use reinit_completion() for repeated operations The driver currently calls init_completion() during every spi_mem_op. Tchnically it may work, but it's not the recommended pattern. According to the kernel documentation: Calling init_completion() on the same completion object twice is most likely a bug as it re-initializes the queue to an empty queue and enqueued tasks could get "lost" - use reinit_completion() in that case, but be aware of other races. So moves the initial initialization to probe function and uses reinit_completion() for subsequent operations. Fixes: 84d043185dbe ("spi: Add a driver for the Freescale/NXP QuadSPI controller") Signed-off-by: Felix Gu Reviewed-by: Haibo Chen Link: https://patch.msgid.link/20260304-spi-nxp-v2-3-cd7d7726a27e@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-qspi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c index a223b4bc6e63..57358851029b 100644 --- a/drivers/spi/spi-fsl-qspi.c +++ b/drivers/spi/spi-fsl-qspi.c @@ -633,7 +633,7 @@ static int fsl_qspi_do_op(struct fsl_qspi *q, const struct spi_mem_op *op) void __iomem *base = q->iobase; int err = 0; - init_completion(&q->c); + reinit_completion(&q->c); /* * Always start the sequence at the same index since we update @@ -965,6 +965,7 @@ static int fsl_qspi_probe(struct platform_device *pdev) if (ret < 0) return ret; + init_completion(&q->c); ret = devm_request_irq(dev, ret, fsl_qspi_irq_handler, 0, pdev->name, q); if (ret) { From ec6c2e15a42fc8fb63baadee0e8a3257e37fa90c Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Sat, 7 Mar 2026 15:47:15 +0800 Subject: [PATCH 018/115] spi: axiado: Remove redundant pm_runtime_mark_last_busy() call The pm_runtime_mark_last_busy() call is redundant in the probe function as pm_runtime_put_autosuspend() already calls pm_runtime_mark_last_busy() internally to update the last access time of the device before queuing autosuspend. Fixes: e75a6b00ad79 ("spi: axiado: Add driver for Axiado SPI DB controller") Signed-off-by: Felix Gu Signed-off-by: Mark Brown Link: https://patch.msgid.link/20260307-axiado-1-v1-1-e90aa1b6dd9b@gmail.com --- drivers/spi/spi-axiado.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/spi/spi-axiado.c b/drivers/spi/spi-axiado.c index 8cea81432c5b..bd5f67acc4f6 100644 --- a/drivers/spi/spi-axiado.c +++ b/drivers/spi/spi-axiado.c @@ -850,7 +850,6 @@ static int ax_spi_probe(struct platform_device *pdev) ctlr->bits_per_word_mask = SPI_BPW_MASK(8); - pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_put_autosuspend(&pdev->dev); ctlr->mem_ops = &ax_spi_mem_ops; From d1008a8e29b09ea57c77ddf82d688f8c2ea6cbe8 Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Sat, 7 Mar 2026 15:24:45 +0800 Subject: [PATCH 019/115] spi: tegra210-quad: Remove redundant pm_runtime_mark_last_busy() calls pm_runtime_put_autosuspend() already internally updates the last_busy timestamp before scheduling the autosuspend, making explicit pm_runtime_mark_last_busy() calls immediately before it redundant. Fixes: 7c12f6ead467 ("spi: tegra210-quad: Add runtime autosuspend support") Signed-off-by: Felix Gu Signed-off-by: Mark Brown Link: https://patch.msgid.link/20260307-quad-v1-1-f103515db501@gmail.com --- drivers/spi/spi-tegra210-quad.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c index 7fac695b5142..7cca5578eba3 100644 --- a/drivers/spi/spi-tegra210-quad.c +++ b/drivers/spi/spi-tegra210-quad.c @@ -1000,7 +1000,6 @@ static int tegra_qspi_setup(struct spi_device *spi) spin_unlock_irqrestore(&tqspi->lock, flags); - pm_runtime_mark_last_busy(tqspi->dev); pm_runtime_put_autosuspend(tqspi->dev); return 0; @@ -1790,7 +1789,6 @@ static int tegra_qspi_probe(struct platform_device *pdev) tqspi->spi_cs_timing2 = tegra_qspi_readl(tqspi, QSPI_CS_TIMING2); tqspi->def_command2_reg = tegra_qspi_readl(tqspi, QSPI_COMMAND2); - pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_put_autosuspend(&pdev->dev); ret = request_threaded_irq(tqspi->irq, NULL, @@ -1851,7 +1849,6 @@ static int __maybe_unused tegra_qspi_resume(struct device *dev) tegra_qspi_writel(tqspi, tqspi->command1_reg, QSPI_COMMAND1); tegra_qspi_writel(tqspi, tqspi->def_command2_reg, QSPI_COMMAND2); - pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); return spi_controller_resume(host); From 97545e37234fdbe457f5104a09f55033550b3d84 Mon Sep 17 00:00:00 2001 From: Pei Xiao Date: Wed, 11 Mar 2026 09:55:13 +0800 Subject: [PATCH 020/115] spi: atcspi200: Use helper function devm_clk_get_enabled() Since commit 7ef9651e9792 ("clk: Provide new devm_clk helpers for prepared and enabled clocks"), devm_clk_get() and clk_prepare_enable() can now be replaced by devm_clk_get_enabled(). Moreover, it is no longer necessary to unprepare and disable the clocks explicitly. Signed-off-by: Pei Xiao Link: https://patch.msgid.link/e53aefc63e28caf32bcd553f3d0a8f2a5a25cd8d.1773193726.git.xiaopei01@kylinos.cn Signed-off-by: Mark Brown --- drivers/spi/spi-atcspi200.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/drivers/spi/spi-atcspi200.c b/drivers/spi/spi-atcspi200.c index 2075058387f3..257db4e529e2 100644 --- a/drivers/spi/spi-atcspi200.c +++ b/drivers/spi/spi-atcspi200.c @@ -486,11 +486,6 @@ static int atcspi_init_resources(struct platform_device *pdev, return dev_err_probe(spi->dev, PTR_ERR(spi->regmap), "Failed to init regmap\n"); - spi->clk = devm_clk_get(spi->dev, NULL); - if (IS_ERR(spi->clk)) - return dev_err_probe(spi->dev, PTR_ERR(spi->clk), - "Failed to get SPI clock\n"); - spi->sclk_rate = ATCSPI_MAX_SPEED_HZ; return 0; } @@ -526,13 +521,10 @@ static int atcspi_configure_dma(struct atcspi_dev *spi) static int atcspi_enable_clk(struct atcspi_dev *spi) { - int ret; - - ret = clk_prepare_enable(spi->clk); - if (ret) - return dev_err_probe(spi->dev, ret, - "Failed to enable clock\n"); - + spi->clk = devm_clk_get_enabled(spi->dev, NULL); + if (IS_ERR(spi->clk)) + return dev_err_probe(spi->dev, PTR_ERR(spi->clk), + "Failed to get SPI clock\n"); spi->clk_rate = clk_get_rate(spi->clk); if (!spi->clk_rate) return dev_err_probe(spi->dev, -EINVAL, @@ -585,15 +577,14 @@ static int atcspi_probe(struct platform_device *pdev) ret = atcspi_setup(spi); if (ret) - goto disable_clk; + goto free_controller; ret = devm_spi_register_controller(&pdev->dev, host); if (ret) { dev_err_probe(spi->dev, ret, "Failed to register SPI controller\n"); - goto disable_clk; + goto free_controller; } - spi->use_dma = false; if (ATCSPI_DMA_SUPPORT) { ret = atcspi_configure_dma(spi); @@ -607,9 +598,6 @@ static int atcspi_probe(struct platform_device *pdev) return 0; -disable_clk: - clk_disable_unprepare(spi->clk); - free_controller: spi_controller_put(host); return ret; From 869d5b4b2a8012f6ef6058a1055cac6922c2cb55 Mon Sep 17 00:00:00 2001 From: Pei Xiao Date: Thu, 12 Mar 2026 10:47:55 +0800 Subject: [PATCH 021/115] spi: atcspi200: fix mutex initialization order The atcspi_exec_mem_op() function may call mutex_lock() on the driver's mutex before it is properly initialized if a SPI memory operation is initiated immediately after devm_spi_register_controller() is called. The mutex initialization currently occurs after the controller registration, which leaves a window where the mutex could be used uninitialized. Move the mutex initialization to the beginning of the probe function, before any registration or resource allocation. Fixes: 34e3815ea459 ("spi: atcspi200: Add ATCSPI200 SPI controller driver") Signed-off-by: Pei Xiao Link: https://patch.msgid.link/15a71241affc25108a97d40d9d3dd1bc3d2d69ed.1773282905.git.xiaopei01@kylinos.cn Signed-off-by: Mark Brown --- drivers/spi/spi-atcspi200.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-atcspi200.c b/drivers/spi/spi-atcspi200.c index 257db4e529e2..8f283dffe3ca 100644 --- a/drivers/spi/spi-atcspi200.c +++ b/drivers/spi/spi-atcspi200.c @@ -565,6 +565,8 @@ static int atcspi_probe(struct platform_device *pdev) spi->dev = &pdev->dev; dev_set_drvdata(&pdev->dev, host); + mutex_init(&spi->mutex_lock); + ret = atcspi_init_resources(pdev, spi, &mem_res); if (ret) goto free_controller; @@ -594,11 +596,11 @@ static int atcspi_probe(struct platform_device *pdev) else spi->use_dma = true; } - mutex_init(&spi->mutex_lock); return 0; free_controller: + mutex_destroy(&spi->mutex_lock); spi_controller_put(host); return ret; } From 8abf84f76a546c320c788cd7a8c5e3abea9b2b38 Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Sun, 8 Mar 2026 14:59:50 +0800 Subject: [PATCH 022/115] spi: amlogic-spisg: Use IS_ERR() instead of IS_ERR_OR_NULL() devm_clk_get_enabled() and devm_clk_hw_get_clk() return error pointers on failure and never return NULL. So IS_ERR_OR_NULL() is unnecessary, replace them with IS_ERR(). Signed-off-by: Felix Gu Link: https://patch.msgid.link/20260308-spisg-1-v1-1-4e209faf228d@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-amlogic-spisg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-amlogic-spisg.c b/drivers/spi/spi-amlogic-spisg.c index 1509df2b17ae..665f889dc8d3 100644 --- a/drivers/spi/spi-amlogic-spisg.c +++ b/drivers/spi/spi-amlogic-spisg.c @@ -647,13 +647,13 @@ static int aml_spisg_clk_init(struct spisg_device *spisg, void __iomem *base) int ret, i; spisg->core = devm_clk_get_enabled(dev, "core"); - if (IS_ERR_OR_NULL(spisg->core)) { + if (IS_ERR(spisg->core)) { dev_err(dev, "core clock request failed\n"); return PTR_ERR(spisg->core); } spisg->pclk = devm_clk_get_enabled(dev, "pclk"); - if (IS_ERR_OR_NULL(spisg->pclk)) { + if (IS_ERR(spisg->pclk)) { dev_err(dev, "pclk clock request failed\n"); return PTR_ERR(spisg->pclk); } @@ -703,7 +703,7 @@ static int aml_spisg_clk_init(struct spisg_device *spisg, void __iomem *base) } spisg->sclk = devm_clk_hw_get_clk(dev, &div->hw, NULL); - if (IS_ERR_OR_NULL(spisg->sclk)) { + if (IS_ERR(spisg->sclk)) { dev_err(dev, "get clock failed\n"); return PTR_ERR(spisg->sclk); } From d5b4cb41b9a244e5571f9a589e77cc38ac5ebcc3 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 12 Mar 2026 16:18:15 +0100 Subject: [PATCH 023/115] spi: drop unused devres statistics allocation Drop the now unused device managed per-cpu statistics allocation. Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260312151817.32100-4-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 53dee314d76a..bfc42b75549a 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -96,25 +96,22 @@ static ssize_t driver_override_show(struct device *dev, } static DEVICE_ATTR_RW(driver_override); -static struct spi_statistics __percpu *spi_alloc_pcpu_stats(struct device *dev) +static struct spi_statistics __percpu *spi_alloc_pcpu_stats(void) { struct spi_statistics __percpu *pcpu_stats; + int cpu; - if (dev) - pcpu_stats = devm_alloc_percpu(dev, struct spi_statistics); - else - pcpu_stats = alloc_percpu_gfp(struct spi_statistics, GFP_KERNEL); + pcpu_stats = alloc_percpu_gfp(struct spi_statistics, GFP_KERNEL); + if (!pcpu_stats) + return NULL; - if (pcpu_stats) { - int cpu; + for_each_possible_cpu(cpu) { + struct spi_statistics *stat; - for_each_possible_cpu(cpu) { - struct spi_statistics *stat; - - stat = per_cpu_ptr(pcpu_stats, cpu); - u64_stats_init(&stat->syncp); - } + stat = per_cpu_ptr(pcpu_stats, cpu); + u64_stats_init(&stat->syncp); } + return pcpu_stats; } @@ -574,7 +571,7 @@ struct spi_device *spi_alloc_device(struct spi_controller *ctlr) return NULL; } - spi->pcpu_statistics = spi_alloc_pcpu_stats(NULL); + spi->pcpu_statistics = spi_alloc_pcpu_stats(); if (!spi->pcpu_statistics) { kfree(spi); spi_controller_put(ctlr); @@ -3194,7 +3191,7 @@ struct spi_controller *__spi_alloc_controller(struct device *dev, if (!ctlr) return NULL; - ctlr->pcpu_statistics = spi_alloc_pcpu_stats(NULL); + ctlr->pcpu_statistics = spi_alloc_pcpu_stats(); if (!ctlr->pcpu_statistics) { kfree(ctlr); return NULL; From edc463d72d697ff22da8ba96c0fcb25f3586d9a2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 12 Mar 2026 16:18:16 +0100 Subject: [PATCH 024/115] spi: fix misleading controller registration kernel-doc The controller reference count is not decremented on registration failures (and has not been for a very long time) contrary to what the outdated kernel-doc says. Drop the entire sentence about return values which are now documented in the Return section. Fixes: b885244eb262 ("[PATCH] spi: add spi_driver to SPI framework") Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260312151817.32100-5-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index bfc42b75549a..34aca18a96d8 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -3388,8 +3388,8 @@ static int spi_controller_id_alloc(struct spi_controller *ctlr, int start, int e * device identification, boards need configuration tables telling which * chip is at which address. * - * This must be called from context that can sleep. It returns zero on - * success, else a negative error code (dropping the controller's refcount). + * This must be called from context that can sleep. + * * After a successful return, the caller is responsible for calling * spi_unregister_controller(). * From 3f174274d2249342df00d43fdef25511c3d3565a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 12 Mar 2026 16:18:17 +0100 Subject: [PATCH 025/115] spi: fix misleading controller deregistration kernel-doc The controller reference count is not decremented on deregistration if the controller has been allocated using devm_spi_alloc_host/target(). Amend the kernel-doc for devm_spi_register_controller() and spi_unregister_controller() so that it reflects this (more recent) behaviour. Fixes: 5e844cc37a5c ("spi: Introduce device-managed SPI controller allocation") Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260312151817.32100-6-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 34aca18a96d8..b5e2f1e1a89e 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -3523,7 +3523,8 @@ static void devm_spi_unregister_controller(void *ctlr) * Context: can sleep * * Register a SPI device as with spi_register_controller() which will - * automatically be unregistered and freed. + * automatically be unregistered (and freed unless it has been allocated using + * devm_spi_alloc_host/target()). * * Return: zero on success, else a negative error code. */ @@ -3557,7 +3558,8 @@ static int __unregister(struct device *dev, void *null) * * This must be called from context that can sleep. * - * Note that this function also drops a reference to the controller. + * Note that this function also drops a reference to the controller unless it + * has been allocated using devm_spi_alloc_host/target(). */ void spi_unregister_controller(struct spi_controller *ctlr) { From c2edd7841f58cf228347b91256f0d9efcc1a1f50 Mon Sep 17 00:00:00 2001 From: Tommaso Merciai Date: Tue, 17 Feb 2026 17:23:46 +0100 Subject: [PATCH 026/115] spi: dt-bindings: renesas,rzv2h-rspi: Document dmas property Document the dmas property to state it must be specified as TX/RX DMA specifier pairs. This clarifies the expected ordering and improves binding readability without changing behavior. Signed-off-by: Tommaso Merciai Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/ea6ed3b82c5a326732adfc0fcdb2922bfcad2591.1771344527.git.tommaso.merciai.xr@bp.renesas.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml b/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml index cf8b733b766d..d6a5338d6521 100644 --- a/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml +++ b/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml @@ -60,6 +60,9 @@ properties: dmas: minItems: 2 maxItems: 10 + description: + Must contain a list of pairs of references to DMA specifiers, one for + transmission, and one for reception. dma-names: minItems: 2 From 5b7ac8ca0eae522735d24f7c5c2296c8094328b1 Mon Sep 17 00:00:00 2001 From: Tommaso Merciai Date: Tue, 17 Feb 2026 17:23:47 +0100 Subject: [PATCH 027/115] spi: dt-bindings: renesas,rzv2h-rspi: Document RZ/G3E SoC support Document the RSPI controller on the Renesas RZ/G3E SoC. The block is compatible with the RSPI implementation found on the RZ/V2H(P) family. Signed-off-by: Tommaso Merciai Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/f6b43f0dc64e13b1c9942c164dea30002d4c4466.1771344527.git.tommaso.merciai.xr@bp.renesas.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml b/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml index d6a5338d6521..2c9045fd51de 100644 --- a/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml +++ b/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml @@ -16,7 +16,9 @@ properties: - renesas,r9a09g057-rspi # RZ/V2H(P) - renesas,r9a09g077-rspi # RZ/T2H - items: - - const: renesas,r9a09g056-rspi # RZ/V2N + - enum: + - renesas,r9a09g047-rspi # RZ/G3E + - renesas,r9a09g056-rspi # RZ/V2N - const: renesas,r9a09g057-rspi - items: - const: renesas,r9a09g087-rspi # RZ/N2H From 9861e15f6347dcce65795b8dd680b491a54d59a9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 23 Mar 2026 15:04:45 +0100 Subject: [PATCH 028/115] spi: Replace open coded variant of spi_bpw_to_bytes() __spi_validate() open codes the functionality of spi_bpw_to_bytes(). Replace the custom piece by the call to the mentioned function. Signed-off-by: Andy Shevchenko Link: https://patch.msgid.link/20260323140445.3496736-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index bf1df365f795..418d69f89162 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -4282,12 +4282,7 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) * SPI transfer length should be multiple of SPI word size * where SPI word size should be power-of-two multiple. */ - if (xfer->bits_per_word <= 8) - w_size = 1; - else if (xfer->bits_per_word <= 16) - w_size = 2; - else - w_size = 4; + w_size = spi_bpw_to_bytes(xfer->bits_per_word); /* No partial transfers accepted */ if (xfer->len % w_size) From a37fb5166be943fa78962f77db00ce5a25366e87 Mon Sep 17 00:00:00 2001 From: Kexin Sun Date: Sat, 21 Mar 2026 18:59:40 +0800 Subject: [PATCH 029/115] spi: pl022: update outdated references to pump_transfers() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pump_transfers tasklet was removed when the driver switched to the SPI core message processing loop in commit 9b2ef250b31d ("spi: spl022: switch to use default spi_transfer_one_message()"). The kdoc of pl022_interrupt_handler() still describes the old flow: scheduling the pump_transfers tasklet, calling giveback(), and flagging STATE_ERROR — none of which exist in the current code. Rewrite the kdoc to reflect the current paths, which flag errors via SPI_TRANS_FAIL_IO and call spi_finalize_current_transfer() directly. Assisted-by: unnamed:deepseek-v3.2 coccinelle Signed-off-by: Kexin Sun Reviewed-by: Linus Walleij Link: https://patch.msgid.link/20260321105940.8143-1-kexinsun@smail.nju.edu.cn Signed-off-by: Mark Brown --- drivers/spi/spi-pl022.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index c82cc522776d..bd1d28caa51e 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -1127,11 +1127,11 @@ static inline void pl022_dma_remove(struct pl022 *pl022) * * This function handles interrupts generated for an interrupt based transfer. * If a receive overrun (ROR) interrupt is there then we disable SSP, flag the - * current message's state as STATE_ERROR and schedule the tasklet - * pump_transfers which will do the postprocessing of the current message by - * calling giveback(). Otherwise it reads data from RX FIFO till there is no - * more data, and writes data in TX FIFO till it is not full. If we complete - * the transfer we move to the next transfer and schedule the tasklet. + * current transfer with SPI_TRANS_FAIL_IO and call + * spi_finalize_current_transfer() to let the core finish the message. + * Otherwise it reads data from RX FIFO till there is no more data, and writes + * data in TX FIFO till it is not full. When the transfer is complete we call + * spi_finalize_current_transfer() so the core can schedule the next one. */ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id) { From e532e21a246d3fde56b7c74d6f730a16291cc96e Mon Sep 17 00:00:00 2001 From: Pei Xiao Date: Thu, 19 Mar 2026 10:03:58 +0800 Subject: [PATCH 030/115] spi: bcm63xx-hsspi: Simplify clock handling with devm_clk_get_enabled() Replace devm_clk_get() followed by clk_prepare_enable() with devm_clk_get_enabled() for both the "hsspi" and "pll" clocks. This reduces boilerplate code and error handling, as the managed API automatically disables the clocks when the device is removed or if probe fails. Remove the now-unnecessary clk_disable_unprepare() calls from the probe error paths and the remove callback. Accordingly, adjust the error handling labels to direct returns where possible. Signed-off-by: Pei Xiao Link: https://patch.msgid.link/3a187be6d9963645f01caebc1169e06f8804b7a6.1773885292.git.xiaopei01@kylinos.cn Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx-hsspi.c | 46 +++++++++------------------------ 1 file changed, 12 insertions(+), 34 deletions(-) diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index 612f8802e690..266eabd3715b 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -758,8 +758,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) if (IS_ERR(regs)) return PTR_ERR(regs); - clk = devm_clk_get(dev, "hsspi"); - + clk = devm_clk_get_enabled(dev, "hsspi"); if (IS_ERR(clk)) return PTR_ERR(clk); @@ -767,41 +766,26 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) if (IS_ERR(reset)) return PTR_ERR(reset); - ret = clk_prepare_enable(clk); - if (ret) - return ret; - ret = reset_control_reset(reset); - if (ret) { - dev_err(dev, "unable to reset device: %d\n", ret); - goto out_disable_clk; - } + if (ret) + return dev_err_probe(dev, ret, "unable to reset device: %d\n", ret); rate = clk_get_rate(clk); if (!rate) { - pll_clk = devm_clk_get(dev, "pll"); - - if (IS_ERR(pll_clk)) { - ret = PTR_ERR(pll_clk); - goto out_disable_clk; - } - - ret = clk_prepare_enable(pll_clk); - if (ret) - goto out_disable_clk; + pll_clk = devm_clk_get_enabled(dev, "pll"); + if (IS_ERR(pll_clk)) + return dev_err_probe(dev, PTR_ERR(pll_clk), + "failed enable pll clk\n"); rate = clk_get_rate(pll_clk); - if (!rate) { - ret = -EINVAL; - goto out_disable_pll_clk; - } + if (!rate) + return dev_err_probe(dev, -EINVAL, + "failed get pll clk rate\n"); } host = spi_alloc_host(&pdev->dev, sizeof(*bs)); - if (!host) { - ret = -ENOMEM; - goto out_disable_pll_clk; - } + if (!host) + return dev_err_probe(dev, -ENOMEM, "alloc host no mem\n"); bs = spi_controller_get_devdata(host); bs->pdev = pdev; @@ -887,10 +871,6 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); out_put_host: spi_controller_put(host); -out_disable_pll_clk: - clk_disable_unprepare(pll_clk); -out_disable_clk: - clk_disable_unprepare(clk); return ret; } @@ -902,8 +882,6 @@ static void bcm63xx_hsspi_remove(struct platform_device *pdev) /* reset the hardware and block queue progress */ __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); - clk_disable_unprepare(bs->pll_clk); - clk_disable_unprepare(bs->clk); sysfs_remove_group(&pdev->dev.kobj, &bcm63xx_hsspi_group); } From 8b237cb10e32791e53a13c3e96e88683a736094a Mon Sep 17 00:00:00 2001 From: Pei Xiao Date: Thu, 19 Mar 2026 10:03:59 +0800 Subject: [PATCH 031/115] spi: bcmbca-hsspi: Simplify clock handling with devm_clk_get_enabled() Replace devm_clk_get() followed by clk_prepare_enable() with devm_clk_get_enabled() for both the "hsspi" and "pll" clocks. This reduces boilerplate code and error handling, as the managed API automatically disables the clocks when the device is removed or if probe fails. Remove the now-unnecessary clk_disable_unprepare() calls from the probe error paths and the remove callback. Simplify the error handling by converting to direct returns with dev_err_probe() where appropriate. Signed-off-by: Pei Xiao Link: https://patch.msgid.link/a3d07ed20d7bdc676fb10c9a73224f80e83b3232.1773885292.git.xiaopei01@kylinos.cn Signed-off-by: Mark Brown --- drivers/spi/spi-bcmbca-hsspi.c | 49 +++++++++++----------------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/drivers/spi/spi-bcmbca-hsspi.c b/drivers/spi/spi-bcmbca-hsspi.c index ece22260f570..2e22345115fd 100644 --- a/drivers/spi/spi-bcmbca-hsspi.c +++ b/drivers/spi/spi-bcmbca-hsspi.c @@ -452,39 +452,30 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev) if (IS_ERR(spim_ctrl)) return PTR_ERR(spim_ctrl); - clk = devm_clk_get(dev, "hsspi"); + clk = devm_clk_get_enabled(dev, "hsspi"); if (IS_ERR(clk)) - return PTR_ERR(clk); - - ret = clk_prepare_enable(clk); - if (ret) - return ret; + return dev_err_probe(dev, PTR_ERR(clk), + "Failed to get hsspi clock\n"); rate = clk_get_rate(clk); if (!rate) { - pll_clk = devm_clk_get(dev, "pll"); + pll_clk = devm_clk_get_enabled(dev, "pll"); if (IS_ERR(pll_clk)) { - ret = PTR_ERR(pll_clk); - goto out_disable_clk; + return dev_err_probe(dev, PTR_ERR(pll_clk), + "Failed to get pll clock\n"); } - ret = clk_prepare_enable(pll_clk); - if (ret) - goto out_disable_clk; - rate = clk_get_rate(pll_clk); - if (!rate) { - ret = -EINVAL; - goto out_disable_pll_clk; - } + if (!rate) + return dev_err_probe(dev, -EINVAL, + "Failed to get pll clock rate\n"); } host = devm_spi_alloc_host(&pdev->dev, sizeof(*bs)); - if (!host) { - ret = -ENOMEM; - goto out_disable_pll_clk; - } + if (!host) + return dev_err_probe(dev, -ENOMEM, + "Failed alloc spi host\n"); bs = spi_controller_get_devdata(host); bs->pdev = pdev; @@ -535,18 +526,16 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev) ret = devm_request_irq(dev, irq, bcmbca_hsspi_interrupt, IRQF_SHARED, pdev->name, bs); if (ret) - goto out_disable_pll_clk; + return dev_err_probe(dev, ret, "Failed request irq\n"); } ret = devm_pm_runtime_enable(&pdev->dev); if (ret) - goto out_disable_pll_clk; + return dev_err_probe(dev, ret, "Failed pm runtime enable\n"); ret = sysfs_create_group(&pdev->dev.kobj, &bcmbca_hsspi_group); - if (ret) { - dev_err(&pdev->dev, "couldn't register sysfs group\n"); - goto out_disable_pll_clk; - } + if (ret) + return dev_err_probe(dev, ret, "couldn't register sysfs group\n"); /* register and we are done */ ret = devm_spi_register_controller(dev, host); @@ -559,10 +548,6 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev) out_sysgroup_disable: sysfs_remove_group(&pdev->dev.kobj, &bcmbca_hsspi_group); -out_disable_pll_clk: - clk_disable_unprepare(pll_clk); -out_disable_clk: - clk_disable_unprepare(clk); return ret; } @@ -573,8 +558,6 @@ static void bcmbca_hsspi_remove(struct platform_device *pdev) /* reset the hardware and block queue progress */ __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); - clk_disable_unprepare(bs->pll_clk); - clk_disable_unprepare(bs->clk); sysfs_remove_group(&pdev->dev.kobj, &bcmbca_hsspi_group); } From 140039c23aca067b9ff0242e3c0ce96276bb95f3 Mon Sep 17 00:00:00 2001 From: Pei Xiao Date: Thu, 19 Mar 2026 10:04:05 +0800 Subject: [PATCH 032/115] spi: sifive: Simplify clock handling with devm_clk_get_enabled() Replace devm_clk_get() followed by clk_prepare_enable() with devm_clk_get_enabled() for the bus clock. This reduces boilerplate code and error handling, as the managed API automatically disables the clock when the device is removed or if probe fails. Remove the now-unnecessary clk_disable_unprepare() calls from the probe error path and the remove callback. Adjust the error handling to use the existing put_host label. Signed-off-by: Pei Xiao Link: https://patch.msgid.link/73d0d8ecb4e1af5a558d6a7866c0f886d94fe3d1.1773885292.git.xiaopei01@kylinos.cn Signed-off-by: Mark Brown --- drivers/spi/spi-sifive.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c index 6c7aba8befa0..54adbc057af6 100644 --- a/drivers/spi/spi-sifive.c +++ b/drivers/spi/spi-sifive.c @@ -312,7 +312,8 @@ static int sifive_spi_probe(struct platform_device *pdev) goto put_host; } - spi->clk = devm_clk_get(&pdev->dev, NULL); + /* Spin up the bus clock before hitting registers */ + spi->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(spi->clk)) { dev_err(&pdev->dev, "Unable to find bus clock\n"); ret = PTR_ERR(spi->clk); @@ -342,13 +343,6 @@ static int sifive_spi_probe(struct platform_device *pdev) goto put_host; } - /* Spin up the bus clock before hitting registers */ - ret = clk_prepare_enable(spi->clk); - if (ret) { - dev_err(&pdev->dev, "Unable to enable bus clock\n"); - goto put_host; - } - /* probe the number of CS lines */ spi->cs_inactive = sifive_spi_read(spi, SIFIVE_SPI_REG_CSDEF); sifive_spi_write(spi, SIFIVE_SPI_REG_CSDEF, 0xffffffffU); @@ -357,14 +351,14 @@ static int sifive_spi_probe(struct platform_device *pdev) if (!cs_bits) { dev_err(&pdev->dev, "Could not auto probe CS lines\n"); ret = -EINVAL; - goto disable_clk; + goto put_host; } num_cs = ilog2(cs_bits) + 1; if (num_cs > SIFIVE_SPI_MAX_CS) { dev_err(&pdev->dev, "Invalid number of spi targets\n"); ret = -EINVAL; - goto disable_clk; + goto put_host; } /* Define our host */ @@ -392,7 +386,7 @@ static int sifive_spi_probe(struct platform_device *pdev) dev_name(&pdev->dev), spi); if (ret) { dev_err(&pdev->dev, "Unable to bind to interrupt\n"); - goto disable_clk; + goto put_host; } dev_info(&pdev->dev, "mapped; irq=%d, cs=%d\n", @@ -401,13 +395,11 @@ static int sifive_spi_probe(struct platform_device *pdev) ret = devm_spi_register_controller(&pdev->dev, host); if (ret < 0) { dev_err(&pdev->dev, "spi_register_host failed\n"); - goto disable_clk; + goto put_host; } return 0; -disable_clk: - clk_disable_unprepare(spi->clk); put_host: spi_controller_put(host); @@ -421,7 +413,6 @@ static void sifive_spi_remove(struct platform_device *pdev) /* Disable all the interrupts just in case */ sifive_spi_write(spi, SIFIVE_SPI_REG_IE, 0); - clk_disable_unprepare(spi->clk); } static int sifive_spi_suspend(struct device *dev) From 7da637804805cee6899c9a682227f328e94822a5 Mon Sep 17 00:00:00 2001 From: Pei Xiao Date: Thu, 19 Mar 2026 10:04:09 +0800 Subject: [PATCH 033/115] spi: stm32: Simplify clock handling with devm_clk_get_enabled() Replace devm_clk_get() followed by clk_prepare_enable() with devm_clk_get_enabled() for the clock. This removes the need for explicit clock enable and disable calls, as the managed API automatically handles clock disabling on device removal or probe failure. Remove the now-unnecessary clk_disable_unprepare() calls from the probe error paths and the remove callback. Also simplify error handling by using dev_err_probe(). Signed-off-by: Pei Xiao Acked-by: Alain Volmat Reviewed-by: Amelie Delaunay Link: https://patch.msgid.link/c8259f582596fd08541b94dce5dbb4cae513e295.1773885292.git.xiaopei01@kylinos.cn Signed-off-by: Mark Brown --- drivers/spi/spi-stm32.c | 62 +++++++++++------------------------------ 1 file changed, 17 insertions(+), 45 deletions(-) diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index 8a7f5a10d4af..be88e62075af 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -2360,25 +2360,20 @@ static int stm32_spi_probe(struct platform_device *pdev) int ret; cfg = of_device_get_match_data(&pdev->dev); - if (!cfg) { - dev_err(&pdev->dev, "Failed to get match data for platform\n"); - return -ENODEV; - } + if (!cfg) + return dev_err_probe(&pdev->dev, -ENODEV, + "Failed to get match data for platform\n"); device_mode = of_property_read_bool(np, "spi-slave"); - if (!cfg->has_device_mode && device_mode) { - dev_err(&pdev->dev, "spi-slave not supported\n"); - return -EPERM; - } + if (!cfg->has_device_mode && device_mode) + return dev_err_probe(&pdev->dev, -EPERM, "spi-slave not supported\n"); if (device_mode) ctrl = devm_spi_alloc_target(&pdev->dev, sizeof(struct stm32_spi)); else ctrl = devm_spi_alloc_host(&pdev->dev, sizeof(struct stm32_spi)); - if (!ctrl) { - dev_err(&pdev->dev, "spi controller allocation failed\n"); - return -ENOMEM; - } + if (!ctrl) + return dev_err_probe(&pdev->dev, -ENOMEM, "spi controller allocation failed\n"); platform_set_drvdata(pdev, ctrl); spi = spi_controller_get_devdata(ctrl); @@ -2409,32 +2404,18 @@ static int stm32_spi_probe(struct platform_device *pdev) return ret; } - spi->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(spi->clk)) { - ret = PTR_ERR(spi->clk); - dev_err(&pdev->dev, "clk get failed: %d\n", ret); - return ret; - } + spi->clk = devm_clk_get_enabled(&pdev->dev, NULL); + if (IS_ERR(spi->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(spi->clk), "clk enabled failed\n"); - ret = clk_prepare_enable(spi->clk); - if (ret) { - dev_err(&pdev->dev, "clk enable failed: %d\n", ret); - return ret; - } spi->clk_rate = clk_get_rate(spi->clk); - if (!spi->clk_rate) { - dev_err(&pdev->dev, "clk rate = 0\n"); - ret = -EINVAL; - goto err_clk_disable; - } + if (!spi->clk_rate) + return dev_err_probe(&pdev->dev, -EINVAL, "clk rate = 0\n"); rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); if (rst) { - if (IS_ERR(rst)) { - ret = dev_err_probe(&pdev->dev, PTR_ERR(rst), - "failed to get reset\n"); - goto err_clk_disable; - } + if (IS_ERR(rst)) + return dev_err_probe(&pdev->dev, PTR_ERR(rst), "failed to get reset\n"); reset_control_assert(rst); udelay(2); @@ -2461,11 +2442,8 @@ static int stm32_spi_probe(struct platform_device *pdev) dev_dbg(spi->dev, "one message max size %d\n", spi->t_size_max); ret = spi->cfg->config(spi); - if (ret) { - dev_err(&pdev->dev, "controller configuration failed: %d\n", - ret); - goto err_clk_disable; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "controller configuration failed: %d\n", ret); ctrl->auto_runtime_pm = true; ctrl->bus_num = pdev->id; @@ -2490,8 +2468,7 @@ static int stm32_spi_probe(struct platform_device *pdev) dev_info(&pdev->dev, "tx dma disabled\n"); spi->dma_tx = NULL; } else { - dev_err_probe(&pdev->dev, ret, "failed to request tx dma channel\n"); - goto err_clk_disable; + return dev_err_probe(&pdev->dev, ret, "failed to request tx dma channel\n"); } } else { ctrl->dma_tx = spi->dma_tx; @@ -2579,8 +2556,6 @@ static int stm32_spi_probe(struct platform_device *pdev) err_dma_tx_release: if (spi->dma_tx) dma_release_channel(spi->dma_tx); -err_clk_disable: - clk_disable_unprepare(spi->clk); return ret; } @@ -2610,9 +2585,6 @@ static void stm32_spi_remove(struct platform_device *pdev) gen_pool_free(spi->sram_pool, (unsigned long)spi->sram_rx_buf, spi->sram_rx_buf_size); - clk_disable_unprepare(spi->clk); - - pinctrl_pm_select_sleep_state(&pdev->dev); } From ea0e916de13426dc62fc349f80bf5326adb17cea Mon Sep 17 00:00:00 2001 From: Pei Xiao Date: Thu, 19 Mar 2026 10:04:10 +0800 Subject: [PATCH 034/115] spi: sunplus-sp7021: Simplify clock handling with devm_clk_get_enabled() Replace devm_clk_get() followed by clk_prepare_enable() with devm_clk_get_enabled() for the clock. This removes the need for explicit clock enable/disable calls and the custom cleanup function, as the managed API automatically handles clock disabling on device removal or probe failure. Remove the now-unnecessary sp7021_spi_disable_unprepare() function and the devm_add_action_or_reset() call. Signed-off-by: Pei Xiao Link: https://patch.msgid.link/fb0bc46107975cfff4eefa9ba96fe7545996ae52.1773885292.git.xiaopei01@kylinos.cn Signed-off-by: Mark Brown --- drivers/spi/spi-sunplus-sp7021.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/spi/spi-sunplus-sp7021.c b/drivers/spi/spi-sunplus-sp7021.c index 789b092fe8c0..35601212fb78 100644 --- a/drivers/spi/spi-sunplus-sp7021.c +++ b/drivers/spi/spi-sunplus-sp7021.c @@ -389,11 +389,6 @@ static int sp7021_spi_target_transfer_one(struct spi_controller *ctlr, struct sp return ret; } -static void sp7021_spi_disable_unprepare(void *data) -{ - clk_disable_unprepare(data); -} - static void sp7021_spi_reset_control_assert(void *data) { reset_control_assert(data); @@ -460,7 +455,7 @@ static int sp7021_spi_controller_probe(struct platform_device *pdev) if (pspim->s_irq < 0) return pspim->s_irq; - pspim->spi_clk = devm_clk_get(dev, NULL); + pspim->spi_clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(pspim->spi_clk)) return dev_err_probe(dev, PTR_ERR(pspim->spi_clk), "clk get fail\n"); @@ -468,14 +463,6 @@ static int sp7021_spi_controller_probe(struct platform_device *pdev) if (IS_ERR(pspim->rstc)) return dev_err_probe(dev, PTR_ERR(pspim->rstc), "rst get fail\n"); - ret = clk_prepare_enable(pspim->spi_clk); - if (ret) - return dev_err_probe(dev, ret, "failed to enable clk\n"); - - ret = devm_add_action_or_reset(dev, sp7021_spi_disable_unprepare, pspim->spi_clk); - if (ret) - return ret; - ret = reset_control_deassert(pspim->rstc); if (ret) return dev_err_probe(dev, ret, "failed to deassert reset\n"); From 9f61daf2c2debe9f5cf4e1a4471e56a89a6fe45a Mon Sep 17 00:00:00 2001 From: Pei Xiao Date: Thu, 19 Mar 2026 11:06:41 +0800 Subject: [PATCH 035/115] spi: hisi-kunpeng: prevent infinite while() loop in hisi_spi_flush_fifo The hisi_spi_flush_fifo()'s inner while loop that lacks any timeout mechanism. Maybe the hardware never becomes empty, the loop will spin forever, causing the CPU to hang. Fix this by adding a inner_limit based on loops_per_jiffy. The inner loop now exits after approximately one jiffy if the FIFO remains non-empty, logs a ratelimited warning, and breaks out of the outer loop. Additionally, add a cpu_relax() inside the busy loop to improve power efficiency. Fixes: c770d8631e18 ("spi: Add HiSilicon SPI Controller Driver for Kunpeng SoCs") Signed-off-by: Pei Xiao Link: https://patch.msgid.link/d834ce28172886bfaeb9c8ca00cfd9bf1c65d5a1.1773889292.git.xiaopei01@kylinos.cn Signed-off-by: Mark Brown --- drivers/spi/spi-hisi-kunpeng.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c index 216a0a91fc47..c42d2a2cdf1e 100644 --- a/drivers/spi/spi-hisi-kunpeng.c +++ b/drivers/spi/spi-hisi-kunpeng.c @@ -196,8 +196,18 @@ static void hisi_spi_flush_fifo(struct hisi_spi *hs) unsigned long limit = loops_per_jiffy << 1; do { - while (hisi_spi_rx_not_empty(hs)) + unsigned long inner_limit = loops_per_jiffy; + + while (hisi_spi_rx_not_empty(hs) && --inner_limit) { readl(hs->regs + HISI_SPI_DOUT); + cpu_relax(); + } + + if (!inner_limit) { + dev_warn_ratelimited(hs->dev, "RX FIFO flush timeout\n"); + break; + } + } while (hisi_spi_busy(hs) && limit--); } From 579a49aaab0814c55595cddf0be9651e37972f6a Mon Sep 17 00:00:00 2001 From: Pei Xiao Date: Thu, 19 Mar 2026 11:06:42 +0800 Subject: [PATCH 036/115] spi: hisi-kunpeng: Add timeout warning in FIFO flush function When flushing the FIFO, the driver waits for the busy flag to clear with a timeout. Change the loop condition to use pre-decrement (--limit) instead of post-decrement (limit--) so that warning message can show. Add a ratelimited warning message to log SPI busy timeout events, aiding in debugging. Signed-off-by: Pei Xiao Link: https://patch.msgid.link/dad95ce42fb5677edfed32bc1f9b3e54df2cf8de.1773889292.git.xiaopei01@kylinos.cn Signed-off-by: Mark Brown --- drivers/spi/spi-hisi-kunpeng.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c index c42d2a2cdf1e..046bd894040b 100644 --- a/drivers/spi/spi-hisi-kunpeng.c +++ b/drivers/spi/spi-hisi-kunpeng.c @@ -208,7 +208,10 @@ static void hisi_spi_flush_fifo(struct hisi_spi *hs) break; } - } while (hisi_spi_busy(hs) && limit--); + } while (hisi_spi_busy(hs) && --limit); + + if (!limit) + dev_warn_ratelimited(hs->dev, "SPI busy timeout\n"); } /* Disable the controller and all interrupts */ From 1c78c2002380a1fe31bfb01a3d5f29809e55a096 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 24 Mar 2026 09:23:22 +0100 Subject: [PATCH 037/115] spi: imx: fix use-after-free on unbind The SPI subsystem frees the controller and any subsystem allocated driver data as part of deregistration (unless the allocation is device managed). Take another reference before deregistering the controller so that the driver data is not freed until the driver is done with it. Fixes: 307c897db762 ("spi: spi-imx: replace struct spi_imx_data::bitbang by pointer to struct spi_controller") Cc: stable@vger.kernel.org # 5.19 Acked-by: Marc Kleine-Budde Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260324082326.901043-2-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 64c6c09e1e7b..a8d90c86a8a1 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -2401,6 +2401,8 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; + spi_controller_get(controller); + spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -2414,6 +2416,8 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); + + spi_controller_put(controller); } static int spi_imx_runtime_resume(struct device *dev) From 53e7a16070feb7d1d4d81a583eaac5e25048b9c3 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 24 Mar 2026 09:23:23 +0100 Subject: [PATCH 038/115] spi: rockchip: fix controller deregistration Make sure to deregister the controller before freeing underlying resources like DMA channels during driver unbind. Fixes: 64e36824b32b ("spi/rockchip: add driver for Rockchip RK3xxx SoCs integrated SPI") Cc: stable@vger.kernel.org # 3.17 Cc: addy ke Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260324082326.901043-3-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-rockchip.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index fd2ebef4903f..eb1992b4178e 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -908,7 +908,7 @@ static int rockchip_spi_probe(struct platform_device *pdev) break; } - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { dev_err(&pdev->dev, "Failed to register controller\n"); goto err_free_dma_rx; @@ -936,6 +936,8 @@ static void rockchip_spi_remove(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); + spi_unregister_controller(ctlr); + pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); From 9c01806506545c3083b7006a6ccd2ac746f1d5a4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 24 Mar 2026 09:23:24 +0100 Subject: [PATCH 039/115] spi: imx: switch to managed controller allocation Switch to device managed controller allocation to simplify error handling and to avoid having to take another reference during deregistration. Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260324082326.901043-4-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 45 ++++++++++++++----------------------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index a8d90c86a8a1..4747899e0646 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -2231,11 +2231,9 @@ static int spi_imx_probe(struct platform_device *pdev) target_mode = devtype_data->has_targetmode && of_property_read_bool(np, "spi-slave"); if (target_mode) - controller = spi_alloc_target(&pdev->dev, - sizeof(struct spi_imx_data)); + controller = devm_spi_alloc_target(&pdev->dev, sizeof(*spi_imx)); else - controller = spi_alloc_host(&pdev->dev, - sizeof(struct spi_imx_data)); + controller = devm_spi_alloc_host(&pdev->dev, sizeof(*spi_imx)); if (!controller) return -ENOMEM; @@ -2304,40 +2302,31 @@ static int spi_imx_probe(struct platform_device *pdev) init_completion(&spi_imx->xfer_done); spi_imx->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); - if (IS_ERR(spi_imx->base)) { - ret = PTR_ERR(spi_imx->base); - goto out_controller_put; - } + if (IS_ERR(spi_imx->base)) + return PTR_ERR(spi_imx->base); + spi_imx->base_phys = res->start; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - ret = irq; - goto out_controller_put; - } + if (irq < 0) + return irq; ret = devm_request_irq(&pdev->dev, irq, spi_imx_isr, 0, dev_name(&pdev->dev), spi_imx); - if (ret) { - dev_err(&pdev->dev, "can't get irq%d: %d\n", irq, ret); - goto out_controller_put; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "can't get irq%d\n", irq); spi_imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); - if (IS_ERR(spi_imx->clk_ipg)) { - ret = PTR_ERR(spi_imx->clk_ipg); - goto out_controller_put; - } + if (IS_ERR(spi_imx->clk_ipg)) + return PTR_ERR(spi_imx->clk_ipg); spi_imx->clk_per = devm_clk_get(&pdev->dev, "per"); - if (IS_ERR(spi_imx->clk_per)) { - ret = PTR_ERR(spi_imx->clk_per); - goto out_controller_put; - } + if (IS_ERR(spi_imx->clk_per)) + return PTR_ERR(spi_imx->clk_per); ret = clk_prepare_enable(spi_imx->clk_per); if (ret) - goto out_controller_put; + return ret; ret = clk_prepare_enable(spi_imx->clk_ipg); if (ret) @@ -2389,8 +2378,6 @@ static int spi_imx_probe(struct platform_device *pdev) clk_disable_unprepare(spi_imx->clk_ipg); out_put_per: clk_disable_unprepare(spi_imx->clk_per); -out_controller_put: - spi_controller_put(controller); return ret; } @@ -2401,8 +2388,6 @@ static void spi_imx_remove(struct platform_device *pdev) struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); int ret; - spi_controller_get(controller); - spi_unregister_controller(controller); ret = pm_runtime_get_sync(spi_imx->dev); @@ -2416,8 +2401,6 @@ static void spi_imx_remove(struct platform_device *pdev) pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); - - spi_controller_put(controller); } static int spi_imx_runtime_resume(struct device *dev) From 4ba75403fb4ddbca370512f409e56fbda2473d36 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 24 Mar 2026 09:23:25 +0100 Subject: [PATCH 040/115] spi: tegra20-slink: switch to managed controller allocation Switch to device managed controller allocation to simplify error handling and to avoid having to take another reference during deregistration. Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260324082326.901043-5-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-tegra20-slink.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index 8c608abd6076..c15c076295cd 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -1007,7 +1007,7 @@ static int tegra_slink_probe(struct platform_device *pdev) cdata = of_device_get_match_data(&pdev->dev); - host = spi_alloc_host(&pdev->dev, sizeof(*tspi)); + host = devm_spi_alloc_host(&pdev->dev, sizeof(*tspi)); if (!host) { dev_err(&pdev->dev, "host allocation failed\n"); return -ENOMEM; @@ -1034,37 +1034,34 @@ static int tegra_slink_probe(struct platform_device *pdev) host->max_speed_hz = 25000000; /* 25MHz */ tspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r); - if (IS_ERR(tspi->base)) { - ret = PTR_ERR(tspi->base); - goto exit_free_host; - } + if (IS_ERR(tspi->base)) + return PTR_ERR(tspi->base); + tspi->phys = r->start; /* disabled clock may cause interrupt storm upon request */ tspi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(tspi->clk)) { ret = PTR_ERR(tspi->clk); - dev_err(&pdev->dev, "Can not get clock %d\n", ret); - goto exit_free_host; + return dev_err_probe(&pdev->dev, ret, "Can not get clock\n"); } tspi->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi"); if (IS_ERR(tspi->rst)) { - dev_err(&pdev->dev, "can not get reset\n"); ret = PTR_ERR(tspi->rst); - goto exit_free_host; + return dev_err_probe(&pdev->dev, ret, "can not get reset\n"); } ret = devm_tegra_core_dev_init_opp_table_common(&pdev->dev); if (ret) - goto exit_free_host; + return ret; tspi->max_buf_size = SLINK_FIFO_DEPTH << 2; tspi->dma_buf_size = DEFAULT_SPI_DMA_BUF_LEN; ret = tegra_slink_init_dma_param(tspi, true); if (ret < 0) - goto exit_free_host; + return ret; ret = tegra_slink_init_dma_param(tspi, false); if (ret < 0) goto exit_rx_dma_free; @@ -1125,14 +1122,13 @@ static int tegra_slink_probe(struct platform_device *pdev) tegra_slink_deinit_dma_param(tspi, false); exit_rx_dma_free: tegra_slink_deinit_dma_param(tspi, true); -exit_free_host: - spi_controller_put(host); + return ret; } static void tegra_slink_remove(struct platform_device *pdev) { - struct spi_controller *host = spi_controller_get(platform_get_drvdata(pdev)); + struct spi_controller *host = platform_get_drvdata(pdev); struct tegra_slink_data *tspi = spi_controller_get_devdata(host); spi_unregister_controller(host); @@ -1146,8 +1142,6 @@ static void tegra_slink_remove(struct platform_device *pdev) if (tspi->rx_dma_chan) tegra_slink_deinit_dma_param(tspi, true); - - spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP From 7f3eb70516c7d3aa30ed8eb609344ffc9885fc51 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 24 Mar 2026 09:23:26 +0100 Subject: [PATCH 041/115] spi: rockchip: switch to managed controller allocation Switch to device managed controller allocation to simplify error handling and to avoid having to take another reference during deregistration. Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260324082326.901043-6-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-rockchip.c | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index eb1992b4178e..14cd1b9d9793 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -767,9 +767,9 @@ static int rockchip_spi_probe(struct platform_device *pdev) target_mode = of_property_read_bool(np, "spi-slave"); if (target_mode) - ctlr = spi_alloc_target(&pdev->dev, sizeof(struct rockchip_spi)); + ctlr = devm_spi_alloc_target(&pdev->dev, sizeof(*rs)); else - ctlr = spi_alloc_host(&pdev->dev, sizeof(struct rockchip_spi)); + ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*rs)); if (!ctlr) return -ENOMEM; @@ -780,35 +780,31 @@ static int rockchip_spi_probe(struct platform_device *pdev) /* Get basic io resource and map it */ rs->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &mem); - if (IS_ERR(rs->regs)) { - ret = PTR_ERR(rs->regs); - goto err_put_ctlr; - } + if (IS_ERR(rs->regs)) + return PTR_ERR(rs->regs); rs->apb_pclk = devm_clk_get_enabled(&pdev->dev, "apb_pclk"); if (IS_ERR(rs->apb_pclk)) { - ret = dev_err_probe(&pdev->dev, PTR_ERR(rs->apb_pclk), - "Failed to get apb_pclk\n"); - goto err_put_ctlr; + return dev_err_probe(&pdev->dev, PTR_ERR(rs->apb_pclk), + "Failed to get apb_pclk\n"); } rs->spiclk = devm_clk_get_enabled(&pdev->dev, "spiclk"); if (IS_ERR(rs->spiclk)) { - ret = dev_err_probe(&pdev->dev, PTR_ERR(rs->spiclk), - "Failed to get spi_pclk\n"); - goto err_put_ctlr; + return dev_err_probe(&pdev->dev, PTR_ERR(rs->spiclk), + "Failed to get spi_pclk\n"); } spi_enable_chip(rs, false); ret = platform_get_irq(pdev, 0); if (ret < 0) - goto err_put_ctlr; + return ret; ret = devm_request_irq(&pdev->dev, ret, rockchip_spi_isr, 0, dev_name(&pdev->dev), ctlr); if (ret) - goto err_put_ctlr; + return ret; rs->dev = &pdev->dev; rs->freq = clk_get_rate(rs->spiclk); @@ -830,10 +826,8 @@ static int rockchip_spi_probe(struct platform_device *pdev) } rs->fifo_len = get_fifo_len(rs); - if (!rs->fifo_len) { - ret = dev_err_probe(&pdev->dev, -EINVAL, "Failed to get fifo length\n"); - goto err_put_ctlr; - } + if (!rs->fifo_len) + return dev_err_probe(&pdev->dev, -EINVAL, "Failed to get fifo length\n"); pm_runtime_set_autosuspend_delay(&pdev->dev, ROCKCHIP_AUTOSUSPEND_TIMEOUT); pm_runtime_use_autosuspend(&pdev->dev); @@ -924,15 +918,13 @@ static int rockchip_spi_probe(struct platform_device *pdev) dma_release_channel(ctlr->dma_tx); err_disable_pm_runtime: pm_runtime_disable(&pdev->dev); -err_put_ctlr: - spi_controller_put(ctlr); return ret; } static void rockchip_spi_remove(struct platform_device *pdev) { - struct spi_controller *ctlr = spi_controller_get(platform_get_drvdata(pdev)); + struct spi_controller *ctlr = platform_get_drvdata(pdev); pm_runtime_get_sync(&pdev->dev); @@ -946,8 +938,6 @@ static void rockchip_spi_remove(struct platform_device *pdev) dma_release_channel(ctlr->dma_tx); if (ctlr->dma_rx) dma_release_channel(ctlr->dma_rx); - - spi_controller_put(ctlr); } #ifdef CONFIG_PM_SLEEP From 762a3847a05c5c229009d36fbd0e2feee9dff81a Mon Sep 17 00:00:00 2001 From: Kexin Sun Date: Sat, 21 Mar 2026 18:59:45 +0800 Subject: [PATCH 042/115] spi: pxa2xx: update outdated reference to pump_transfers() The function pump_transfers() was split into pxa2xx_spi_transfer_one(), pxa2xx_spi_handle_err() and pxa2xx_spi_set_cs() in commit d5898e19c0d7 ("spi: pxa2xx: Use core message processing loop"). The comment in pxa2xx_spi_dma_transfer_complete() still warns about concurrent calls to pump_transfers(), but the actual operation protected by dma_running is now spi_finalize_current_transfer(). Update the reference. Assisted-by: unnamed:deepseek-v3.2 coccinelle Signed-off-by: Kexin Sun Link: https://patch.msgid.link/20260321105945.8224-1-kexinsun@smail.nju.edu.cn Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx-dma.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c index 08cb6e96ac94..c94d1d192e74 100644 --- a/drivers/spi/spi-pxa2xx-dma.c +++ b/drivers/spi/spi-pxa2xx-dma.c @@ -29,9 +29,9 @@ static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data, /* * It is possible that one CPU is handling ROR interrupt and other - * just gets DMA completion. Calling pump_transfers() twice for the - * same transfer leads to problems thus we prevent concurrent calls - * by using dma_running. + * just gets DMA completion. Calling spi_finalize_current_transfer() + * twice for the same transfer leads to problems thus we prevent + * concurrent calls by using dma_running. */ if (atomic_dec_and_test(&drv_data->dma_running)) { /* From b99e3ddb91b499d920e63a2daff8880be68cfe9e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2026 11:43:04 +0100 Subject: [PATCH 043/115] spi: ch341: fix memory leaks on probe failures Make sure to deregister the controller, disable pins, and kill and free the RX URB on probe failures to mirror disconnect and avoid memory leaks and use-after-free. Also add an explicit URB kill on disconnect for symmetry (even if that is not strictly required as USB core would have stopped it in the current setup). Fixes: 8846739f52af ("spi: add ch341a usb2spi driver") Cc: stable@vger.kernel.org # 6.11 Cc: Johannes Thumshirn Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260327104305.1309915-2-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-ch341.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-ch341.c b/drivers/spi/spi-ch341.c index 79d2f9ab4ef0..ded093566260 100644 --- a/drivers/spi/spi-ch341.c +++ b/drivers/spi/spi-ch341.c @@ -173,17 +173,17 @@ static int ch341_probe(struct usb_interface *intf, ch341->tx_buf = devm_kzalloc(&udev->dev, CH341_PACKET_LENGTH, GFP_KERNEL); - if (!ch341->tx_buf) - return -ENOMEM; + if (!ch341->tx_buf) { + ret = -ENOMEM; + goto err_free_urb; + } usb_fill_bulk_urb(ch341->rx_urb, udev, ch341->read_pipe, ch341->rx_buf, ch341->rx_len, ch341_recv, ch341); ret = usb_submit_urb(ch341->rx_urb, GFP_KERNEL); - if (ret) { - usb_free_urb(ch341->rx_urb); - return -ENOMEM; - } + if (ret) + goto err_free_urb; ctrl->bus_num = -1; ctrl->mode_bits = SPI_CPHA; @@ -195,21 +195,34 @@ static int ch341_probe(struct usb_interface *intf, ret = ch341_config_stream(ch341); if (ret) - return ret; + goto err_kill_urb; ret = ch341_enable_pins(ch341, true); if (ret) - return ret; + goto err_kill_urb; ret = spi_register_controller(ctrl); if (ret) - return ret; + goto err_disable_pins; ch341->spidev = spi_new_device(ctrl, &chip); - if (!ch341->spidev) - return -ENOMEM; + if (!ch341->spidev) { + ret = -ENOMEM; + goto err_unregister; + } return 0; + +err_unregister: + spi_unregister_controller(ctrl); +err_disable_pins: + ch341_enable_pins(ch341, false); +err_kill_urb: + usb_kill_urb(ch341->rx_urb); +err_free_urb: + usb_free_urb(ch341->rx_urb); + + return ret; } static void ch341_disconnect(struct usb_interface *intf) @@ -219,6 +232,7 @@ static void ch341_disconnect(struct usb_interface *intf) spi_unregister_device(ch341->spidev); spi_unregister_controller(ch341->ctrl); ch341_enable_pins(ch341, false); + usb_kill_urb(ch341->rx_urb); usb_free_urb(ch341->rx_urb); } From abe572f630bc1f0e77041012ab075869036ede4f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2026 11:43:05 +0100 Subject: [PATCH 044/115] spi: ch341: fix devres lifetime USB drivers bind to USB interfaces and any device managed resources should have their lifetime tied to the interface rather than parent USB device. This avoids issues like memory leaks when drivers are unbound without their devices being physically disconnected (e.g. on probe deferral or configuration changes). Fix the controller and driver data lifetime so that they are released on driver unbind. Note that this also makes sure that the SPI controller is placed correctly under the USB interface in the device tree. Fixes: 8846739f52af ("spi: add ch341a usb2spi driver") Cc: stable@vger.kernel.org # 6.11 Cc: Johannes Thumshirn Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260327104305.1309915-3-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-ch341.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-ch341.c b/drivers/spi/spi-ch341.c index ded093566260..3eaa8f176f63 100644 --- a/drivers/spi/spi-ch341.c +++ b/drivers/spi/spi-ch341.c @@ -152,7 +152,7 @@ static int ch341_probe(struct usb_interface *intf, if (ret) return ret; - ctrl = devm_spi_alloc_host(&udev->dev, sizeof(struct ch341_spi_dev)); + ctrl = devm_spi_alloc_host(&intf->dev, sizeof(struct ch341_spi_dev)); if (!ctrl) return -ENOMEM; @@ -163,7 +163,7 @@ static int ch341_probe(struct usb_interface *intf, ch341->read_pipe = usb_rcvbulkpipe(udev, usb_endpoint_num(in)); ch341->rx_len = usb_endpoint_maxp(in); - ch341->rx_buf = devm_kzalloc(&udev->dev, ch341->rx_len, GFP_KERNEL); + ch341->rx_buf = devm_kzalloc(&intf->dev, ch341->rx_len, GFP_KERNEL); if (!ch341->rx_buf) return -ENOMEM; @@ -171,8 +171,7 @@ static int ch341_probe(struct usb_interface *intf, if (!ch341->rx_urb) return -ENOMEM; - ch341->tx_buf = - devm_kzalloc(&udev->dev, CH341_PACKET_LENGTH, GFP_KERNEL); + ch341->tx_buf = devm_kzalloc(&intf->dev, CH341_PACKET_LENGTH, GFP_KERNEL); if (!ch341->tx_buf) { ret = -ENOMEM; goto err_free_urb; From 8292eded59980eb2be64a22819885ab808f03440 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 19 Mar 2026 17:55:35 +0100 Subject: [PATCH 045/115] spi: spi-fsl-lpspi: adapt to kernel coding style Adapt the driver to current kernel coding style standards. Signed-off-by: Marc Kleine-Budde Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-cleanups-v2-1-02b56c5d44a8@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-lpspi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index b361c1bb3e43..989d0ffddc25 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -112,8 +112,8 @@ struct fsl_lpspi_data { void *rx_buf; const void *tx_buf; - void (*tx)(struct fsl_lpspi_data *); - void (*rx)(struct fsl_lpspi_data *); + void (*tx)(struct fsl_lpspi_data *fsl_lpspi); + void (*rx)(struct fsl_lpspi_data *fsl_lpspi); u32 remain; u8 watermark; @@ -271,8 +271,9 @@ static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi) } fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE); - } else + } else { fsl_lpspi_intctrl(fsl_lpspi, IER_TDIE); + } } static void fsl_lpspi_read_rx_fifo(struct fsl_lpspi_data *fsl_lpspi) @@ -348,11 +349,10 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi) return -EINVAL; } - if (config.speed_hz > perclk_rate / 2) { + if (config.speed_hz > perclk_rate / 2) div = 2; - } else { + else div = DIV_ROUND_UP(perclk_rate, config.speed_hz); - } for (prescale = 0; prescale <= prescale_max; prescale++) { scldiv = div / (1 << prescale) - 2; From 732b903ea3e2e95e11990a698df8e18537aeef19 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 19 Mar 2026 17:55:36 +0100 Subject: [PATCH 046/115] spi: spi-fsl-lpspi: fsl_lpspi_set_watermark(): use FIELD_PREP() to encode FIFO Control register Instead of open coding mask and shift operations and to increase readability use FIELD_PREP() to encode the FIFO Control register. Signed-off-by: Marc Kleine-Budde Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-cleanups-v2-2-02b56c5d44a8@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-lpspi.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index 989d0ffddc25..fdd14caf6659 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -75,6 +75,8 @@ #define CFGR1_PCSPOL_MASK GENMASK(11, 8) #define CFGR1_NOSTALL BIT(3) #define CFGR1_HOST BIT(0) +#define FCR_RXWATER GENMASK(18, 16) +#define FCR_TXWATER GENMASK(2, 0) #define FSR_TXCOUNT (0xFF) #define RSR_RXEMPTY BIT(1) #define TCR_CPOL BIT(31) @@ -319,17 +321,18 @@ static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi, static void fsl_lpspi_set_watermark(struct fsl_lpspi_data *fsl_lpspi) { + u8 watermark = fsl_lpspi->watermark >> 1; u32 temp; if (!fsl_lpspi->usedma) - temp = fsl_lpspi->watermark >> 1 | - (fsl_lpspi->watermark >> 1) << 16; + temp = FIELD_PREP(FCR_TXWATER, watermark) | + FIELD_PREP(FCR_RXWATER, watermark); else - temp = fsl_lpspi->watermark >> 1; + temp = FIELD_PREP(FCR_TXWATER, watermark); writel(temp, fsl_lpspi->base + IMX7ULP_FCR); - dev_dbg(fsl_lpspi->dev, "FCR=0x%x\n", temp); + dev_dbg(fsl_lpspi->dev, "FCR=0x%08x\n", temp); } static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi) From b191fbf446bcabe310d3d9ac759e4a071b74186d Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 19 Mar 2026 17:55:38 +0100 Subject: [PATCH 047/115] spi: spi-fsl-lpspi: fsl_lpspi_set_cmd(): use mode from struct fsl_lpspi_data::config::mode Commit 7ae4d097b752 ("spi: spi-fsl-lpspi: Handle clock polarity and phase") enhances the driver with clock polarity and phase handling. That commit adds a 2nd argument ("struct spi_device *spi") to the fsl_lpspi_set_cmd() function. The "spi" pointer is used to access the "mode" of the current transfer. However the mode is already available via "fsl_lpspi->config.mode". To simplify the driver remove the 2nd argument and use "fsl_lpspi->config.mode" to access the mode. Cc: Marek Vasut Reviewed-by: Marek Vasut Signed-off-by: Marc Kleine-Budde Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-cleanups-v2-4-02b56c5d44a8@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-lpspi.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index fdd14caf6659..0b6c7b9c8ffa 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -284,8 +284,7 @@ static void fsl_lpspi_read_rx_fifo(struct fsl_lpspi_data *fsl_lpspi) fsl_lpspi->rx(fsl_lpspi); } -static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi, - struct spi_device *spi) +static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi) { u32 temp = 0; @@ -308,10 +307,10 @@ static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi, } } - if (spi->mode & SPI_CPOL) + if (fsl_lpspi->config.mode & SPI_CPOL) temp |= TCR_CPOL; - if (spi->mode & SPI_CPHA) + if (fsl_lpspi->config.mode & SPI_CPHA) temp |= TCR_CPHA; writel(temp, fsl_lpspi->base + IMX7ULP_TCR); @@ -528,7 +527,7 @@ static int fsl_lpspi_prepare_message(struct spi_controller *controller, if (ret < 0) return ret; - fsl_lpspi_set_cmd(fsl_lpspi, spi); + fsl_lpspi_set_cmd(fsl_lpspi); /* No IRQs */ writel(0, fsl_lpspi->base + IMX7ULP_IER); @@ -808,7 +807,7 @@ static int fsl_lpspi_transfer_one(struct spi_controller *controller, t->effective_speed_hz = fsl_lpspi->config.effective_speed_hz; - fsl_lpspi_set_cmd(fsl_lpspi, spi); + fsl_lpspi_set_cmd(fsl_lpspi); fsl_lpspi->is_first_byte = false; if (fsl_lpspi->usedma) From 1712be8623b2befe4556da320b3f06a767ca5339 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 19 Mar 2026 17:55:39 +0100 Subject: [PATCH 048/115] spi: spi-fsl-lpspi: fsl_lpspi_set_cmd(): remove obfuscated and obsolete assignment of TCR_CPOL and SPI_CPHA Commit 7ae4d097b752 ("spi: spi-fsl-lpspi: Handle clock polarity and phase") enhances the driver with clock polarity and phase handling. Among other things that commit in fsl_lpspi_set_cmd() explicitly set the bits TCR_CPOL and TCR_CPHA bits in the TCR register depending on their corresponding bits in the SPI mode (SPI_CPOL and SPI_CPHA), to configure clock polarity and phase. That change made the assignment of the lowest 2 bits of lpspi_config::mode shifted by << 30 to the TCR register obsolete. The lowest 2 bits of struct lpspi_config::mode (= SPI_CPOL and SPI_CPHA) match the corresponding bits in the TCR register (TCR_CPOL and TCR_CPHA) if shifted. Keep the better readable and maintainable version provided in commit 7ae4d097b752 ("spi: spi-fsl-lpspi: Handle clock polarity and phase") and remove the obfuscated version. Cc: Marek Vasut Signed-off-by: Marc Kleine-Budde Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-cleanups-v2-5-02b56c5d44a8@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-lpspi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index 0b6c7b9c8ffa..f35273d389c8 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -289,7 +289,6 @@ static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi) u32 temp = 0; temp |= fsl_lpspi->config.bpw - 1; - temp |= (fsl_lpspi->config.mode & 0x3) << 30; temp |= (fsl_lpspi->config.chip_select & 0x3) << 24; if (!fsl_lpspi->is_target) { temp |= fsl_lpspi->config.prescale << 27; From c6e178460434e6dad2b948f501cc6811a2e6de8f Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 19 Mar 2026 17:55:40 +0100 Subject: [PATCH 049/115] spi: spi-fsl-lpspi: fsl_lpspi_set_cmd(): use FIELD_PREP to encode Transmit Command register Instead of open coding mask and shift operations and to increase readability use FIELD_PREP() to encode the Transmit Command register. Signed-off-by: Marc Kleine-Budde Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-cleanups-v2-6-02b56c5d44a8@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-lpspi.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index f35273d389c8..25e657227013 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -81,10 +81,14 @@ #define RSR_RXEMPTY BIT(1) #define TCR_CPOL BIT(31) #define TCR_CPHA BIT(30) +#define TCR_MODE GENMASK(31, 30) +#define TCR_PRESCALE GENMASK(29, 27) +#define TCR_PCS GENMASK(25, 24) #define TCR_CONT BIT(21) #define TCR_CONTC BIT(20) #define TCR_RXMSK BIT(19) #define TCR_TXMSK BIT(18) +#define TCR_FRAMESZ GENMASK(11, 0) #define SR_CLEAR_MASK GENMASK(13, 8) @@ -288,10 +292,10 @@ static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi) { u32 temp = 0; - temp |= fsl_lpspi->config.bpw - 1; - temp |= (fsl_lpspi->config.chip_select & 0x3) << 24; + temp |= FIELD_PREP(TCR_FRAMESZ, fsl_lpspi->config.bpw - 1); + temp |= FIELD_PREP(TCR_PCS, fsl_lpspi->config.chip_select); if (!fsl_lpspi->is_target) { - temp |= fsl_lpspi->config.prescale << 27; + temp |= FIELD_PREP(TCR_PRESCALE, fsl_lpspi->config.prescale); /* * Set TCR_CONT will keep SS asserted after current transfer. * For the first transfer, clear TCR_CONTC to assert SS. From ca431d50bf62cca8f0a502e76b3d75ee371af32c Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 19 Mar 2026 17:55:41 +0100 Subject: [PATCH 050/115] spi: spi-fsl-lpspi: fsl_lpspi_setup_transfer(): remove useless spi_transfer NULL pointer check fsl_lpspi_setup_transfer() is either called via: | fsl_lpspi_prepare_message() | -> fsl_lpspi_setup_transfer() or | -> spi_transfer_one_message() | -> controller->transfer_one == fsl_lpspi_transfer_one() | -> fsl_lpspi_setup_transfer() The first call path already has a spi_transfer NULL pointer check, the second one explicitly iterates over all spi_transfer of the spi_message. Simplify the code by removing the useless NULL pointer check. Signed-off-by: Marc Kleine-Budde Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-cleanups-v2-7-02b56c5d44a8@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-lpspi.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index 25e657227013..904195f7b050 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -471,9 +471,6 @@ static int fsl_lpspi_setup_transfer(struct spi_controller *controller, struct fsl_lpspi_data *fsl_lpspi = spi_controller_get_devdata(spi->controller); - if (t == NULL) - return -EINVAL; - fsl_lpspi->config.mode = spi->mode; fsl_lpspi->config.bpw = t->bits_per_word; fsl_lpspi->config.speed_hz = t->speed_hz; From e59fe5e0c418da4cf0432faa0fc9062d56bd98b1 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 19 Mar 2026 17:55:42 +0100 Subject: [PATCH 051/115] spi: spi-fsl-lpspi: fsl_lpspi_can_dma(): directly assign return value to fsl_lpspi->usedma The function fsl_lpspi_can_dma() returns a bool. Simplify the code, remove the if/else and assign the return value of fsl_lpspi_can_dma() directly to fsl_lpspi->usedma. Signed-off-by: Marc Kleine-Budde Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-cleanups-v2-8-02b56c5d44a8@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-lpspi.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index 904195f7b050..577403026c68 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -519,10 +519,7 @@ static int fsl_lpspi_prepare_message(struct spi_controller *controller, fsl_lpspi->usedma = false; ret = fsl_lpspi_setup_transfer(controller, spi, t); - if (fsl_lpspi_can_dma(controller, spi, t)) - fsl_lpspi->usedma = true; - else - fsl_lpspi->usedma = false; + fsl_lpspi->usedma = fsl_lpspi_can_dma(controller, spi, t); if (ret < 0) return ret; @@ -796,10 +793,7 @@ static int fsl_lpspi_transfer_one(struct spi_controller *controller, spi_controller_get_devdata(controller); int ret; - if (fsl_lpspi_can_dma(controller, spi, t)) - fsl_lpspi->usedma = true; - else - fsl_lpspi->usedma = false; + fsl_lpspi->usedma = fsl_lpspi_can_dma(controller, spi, t); ret = fsl_lpspi_setup_transfer(controller, spi, t); if (ret < 0) From b326c71d4e6f9623ee137bccf8205e4327aa1914 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 19 Mar 2026 17:55:43 +0100 Subject: [PATCH 052/115] spi: spi-fsl-lpspi: fsl_lpspi_reset(): convert to void function The function fsl_lpspi_reset() cannot fail and it's return value is never checked. Simplify the code and convert it into a void function. Signed-off-by: Marc Kleine-Budde Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-cleanups-v2-9-02b56c5d44a8@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-lpspi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index 577403026c68..7bc14e56dacc 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -573,7 +573,7 @@ static int fsl_lpspi_wait_for_completion(struct spi_controller *controller) return 0; } -static int fsl_lpspi_reset(struct fsl_lpspi_data *fsl_lpspi) +static void fsl_lpspi_reset(struct fsl_lpspi_data *fsl_lpspi) { u32 temp; @@ -588,8 +588,6 @@ static int fsl_lpspi_reset(struct fsl_lpspi_data *fsl_lpspi) /* W1C for all flags in SR */ writel(SR_CLEAR_MASK, fsl_lpspi->base + IMX7ULP_SR); - - return 0; } static void fsl_lpspi_dma_rx_callback(void *cookie) From 4ef7fa7bca5728a3f61c28da73d7714ed1f303a6 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 19 Mar 2026 17:55:44 +0100 Subject: [PATCH 053/115] spi: spi-fsl-lpspi: fsl_lpspi_write_tx_fifo(): simplify while() loop check To simplify the loop check. Combine both conditions of the while() and the directly following if() into the while(). Signed-off-by: Marc Kleine-Budde Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-cleanups-v2-10-02b56c5d44a8@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-lpspi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index 7bc14e56dacc..3771fed7ea3f 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -262,9 +262,7 @@ static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi) txfifo_cnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff; - while (txfifo_cnt < fsl_lpspi->txfifosize) { - if (!fsl_lpspi->remain) - break; + while (txfifo_cnt < fsl_lpspi->txfifosize && fsl_lpspi->remain) { fsl_lpspi->tx(fsl_lpspi); txfifo_cnt++; } From baa1cb259cc7f034435c3b8dad3e14267e2e6153 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 19 Mar 2026 17:55:45 +0100 Subject: [PATCH 054/115] spi: spi-fsl-lpspi: make struct lpspi_config::mode u32 The struct lpspi_config::mode holds a copy of the mode of struct spi_device::mode. In commit 937e6d756422 ("spi: expand mode support") the struct spi_device::mode was increased from u16 to u32. Increase the struct lpspi_config::mode to u32 avoid truncating the mode variable. Signed-off-by: Marc Kleine-Budde Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-cleanups-v2-11-02b56c5d44a8@pengutronix.de 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 3771fed7ea3f..d266216ed5cb 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -101,7 +101,7 @@ struct lpspi_config { u8 bpw; u8 chip_select; u8 prescale; - u16 mode; + u32 mode; u32 speed_hz; u32 effective_speed_hz; }; From fdca270f8f87cae2eb5b619234b9dd11a863ce6b Mon Sep 17 00:00:00 2001 From: Pei Xiao Date: Tue, 7 Apr 2026 15:30:28 +0800 Subject: [PATCH 055/115] spi: uniphier: Simplify clock handling with devm_clk_get_enabled() Replace devm_clk_get() followed by clk_prepare_enable() with devm_clk_get_enabled() for the clock. This removes the need for explicit clock enable and disable calls, as the managed API automatically handles clock disabling on device removal or probe failure. Remove the now-unnecessary clk_disable_unprepare() calls from the probe error path and the remove callback. Adjust error labels accordingly. Signed-off-by: Pei Xiao Reviewed-by: Kunihiko Hayashi Link: https://patch.msgid.link/b2deeefd4ef1a4bce71116aabfcb7e81400f6d37.1775546948.git.xiaopei01@kylinos.cn Signed-off-by: Mark Brown --- drivers/spi/spi-uniphier.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/spi/spi-uniphier.c b/drivers/spi/spi-uniphier.c index 9e1d364a6198..1b815ee2ed1b 100644 --- a/drivers/spi/spi-uniphier.c +++ b/drivers/spi/spi-uniphier.c @@ -666,28 +666,24 @@ static int uniphier_spi_probe(struct platform_device *pdev) } priv->base_dma_addr = res->start; - priv->clk = devm_clk_get(&pdev->dev, NULL); + priv->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(priv->clk)) { dev_err(&pdev->dev, "failed to get clock\n"); ret = PTR_ERR(priv->clk); goto out_host_put; } - ret = clk_prepare_enable(priv->clk); - if (ret) - goto out_host_put; - irq = platform_get_irq(pdev, 0); if (irq < 0) { ret = irq; - goto out_disable_clk; + goto out_host_put; } ret = devm_request_irq(&pdev->dev, irq, uniphier_spi_handler, 0, "uniphier-spi", priv); if (ret) { dev_err(&pdev->dev, "failed to request IRQ\n"); - goto out_disable_clk; + goto out_host_put; } init_completion(&priv->xfer_done); @@ -716,7 +712,7 @@ static int uniphier_spi_probe(struct platform_device *pdev) if (IS_ERR_OR_NULL(host->dma_tx)) { if (PTR_ERR(host->dma_tx) == -EPROBE_DEFER) { ret = -EPROBE_DEFER; - goto out_disable_clk; + goto out_host_put; } host->dma_tx = NULL; dma_tx_burst = INT_MAX; @@ -766,9 +762,6 @@ static int uniphier_spi_probe(struct platform_device *pdev) host->dma_tx = NULL; } -out_disable_clk: - clk_disable_unprepare(priv->clk); - out_host_put: spi_controller_put(host); return ret; @@ -777,14 +770,11 @@ static int uniphier_spi_probe(struct platform_device *pdev) static void uniphier_spi_remove(struct platform_device *pdev) { struct spi_controller *host = platform_get_drvdata(pdev); - struct uniphier_spi_priv *priv = spi_controller_get_devdata(host); if (host->dma_tx) dma_release_channel(host->dma_tx); if (host->dma_rx) dma_release_channel(host->dma_rx); - - clk_disable_unprepare(priv->clk); } static const struct of_device_id uniphier_spi_match[] = { From 5277c291968d87c6a093f50ef489df9d52cb3ca9 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Wed, 8 Apr 2026 09:54:14 +0100 Subject: [PATCH 056/115] spi: dt-bindings: renesas,rzv2h-rspi: Document RZ/G3L SoC Document RSPI IP found on the RZ/G3L SoC. The RSPI IP is compatible with the RZ/V2H RSPI IP, but has 2 clocks compared to 3 on RZ/V2H. Reviewed-by: Krzysztof Kozlowski Reviewed-by: Geert Uytterhoeven Signed-off-by: Biju Das Link: https://patch.msgid.link/20260408085418.18770-2-biju.das.jz@bp.renesas.com Signed-off-by: Mark Brown --- .../bindings/spi/renesas,rzv2h-rspi.yaml | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml b/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml index a588b112e11e..b42ea82ea883 100644 --- a/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml +++ b/Documentation/devicetree/bindings/spi/renesas,rzv2h-rspi.yaml @@ -13,6 +13,7 @@ properties: compatible: oneOf: - enum: + - renesas,r9a08g046-rspi # RZ/G3L - renesas,r9a09g057-rspi # RZ/V2H(P) - renesas,r9a09g077-rspi # RZ/T2H - items: @@ -81,6 +82,34 @@ required: allOf: - $ref: spi-controller.yaml# + - if: + properties: + compatible: + contains: + enum: + - renesas,r9a08g046-rspi + then: + properties: + clocks: + maxItems: 2 + + clock-names: + items: + - const: pclk + - const: tclk + + dmas: + maxItems: 2 + + dma-names: + items: + - const: rx + - const: tx + + required: + - resets + - reset-names + - if: properties: compatible: From 9be1143516473694ffd731304198a8b02e832d1d Mon Sep 17 00:00:00 2001 From: Biju Das Date: Wed, 8 Apr 2026 09:54:15 +0100 Subject: [PATCH 057/115] spi: rzv2h-rspi: Add support for RZ/G3L (R9A08G046) Add support for RZ/G3L RSPI. The RZ/G3L variant requires only 2 clocks (pclk + tclk), unlike the RZ/V2H which needs 3. Reviewed-by: Geert Uytterhoeven Signed-off-by: Biju Das Link: https://patch.msgid.link/20260408085418.18770-3-biju.das.jz@bp.renesas.com Signed-off-by: Mark Brown --- drivers/spi/spi-rzv2h-rspi.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/spi/spi-rzv2h-rspi.c b/drivers/spi/spi-rzv2h-rspi.c index 23f0e92ae208..38ee09e389c9 100644 --- a/drivers/spi/spi-rzv2h-rspi.c +++ b/drivers/spi/spi-rzv2h-rspi.c @@ -811,6 +811,13 @@ static const struct rzv2h_rspi_info rzv2h_info = { .num_clks = 3, }; +static const struct rzv2h_rspi_info rzg3l_info = { + .find_tclk_rate = rzv2h_rspi_find_rate_fixed, + .tclk_name = "tclk", + .fifo_size = 16, + .num_clks = 2, +}; + static const struct rzv2h_rspi_info rzt2h_info = { .find_tclk_rate = rzv2h_rspi_find_rate_variable, .find_pclk_rate = rzv2h_rspi_find_rate_fixed, @@ -820,6 +827,7 @@ static const struct rzv2h_rspi_info rzt2h_info = { }; static const struct of_device_id rzv2h_rspi_match[] = { + { .compatible = "renesas,r9a08g046-rspi", &rzg3l_info }, { .compatible = "renesas,r9a09g057-rspi", &rzv2h_info }, { .compatible = "renesas,r9a09g077-rspi", &rzt2h_info }, { /* sentinel */ } From 484eb2c4cc7f788a68c11abc477c065a79cfc0d6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 8 Apr 2026 10:44:07 +0200 Subject: [PATCH 058/115] spi: pl022: enable compile testing There seems to be nothing preventing this driver from being compile tested so enable that for wider build coverage. Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260408084407.107416-1-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index c3b2f02f5912..ddd53cb48567 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -866,7 +866,7 @@ config SPI_PIC32_SQI config SPI_PL022 tristate "ARM AMBA PL022 SSP controller" - depends on ARM_AMBA + depends on ARM_AMBA || COMPILE_TEST default y if ARCH_REALVIEW default y if INTEGRATOR_IMPD1 default y if ARCH_VERSATILE From 5bbc10c50a35490624b86f457ead53054dcd0b34 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 16:56:18 +0200 Subject: [PATCH 059/115] spi: atcspi200: enable compile testing There seems to be nothing preventing this driver from being compile tested so enable that for wider build coverage. Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260409145618.466701-1-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index ddd53cb48567..b563f49e2197 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -138,7 +138,7 @@ config SPI_AR934X config SPI_ATCSPI200 tristate "Andes ATCSPI200 SPI controller" - depends on ARCH_ANDES + depends on ARCH_ANDES || COMPILE_TEST help SPI driver for Andes ATCSPI200 SPI controller. ATCSPI200 controller supports DMA and PIO modes. When DMA From 48c0d3c6a4a2e32c5acccd1129896b33a1f5046b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:08:10 +0200 Subject: [PATCH 060/115] spi: npcm-fiu: drop unused remove callback Drop the remove callback which is unused since commit 82c4fadb0b95 ("spi: npcm-fiu: Use helper function devm_clk_get_enabled()"). The above mentioned commit also removed the last user of the platform driver data which no longer needs to be set (twice). Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260409120810.388909-1-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-npcm-fiu.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/spi/spi-npcm-fiu.c b/drivers/spi/spi-npcm-fiu.c index 3961b0ccdb4b..6617751009c3 100644 --- a/drivers/spi/spi-npcm-fiu.c +++ b/drivers/spi/spi-npcm-fiu.c @@ -715,7 +715,6 @@ static int npcm_fiu_probe(struct platform_device *pdev) fiu->info = &fiu_data_match->npcm_fiu_data_info[id]; - platform_set_drvdata(pdev, fiu); fiu->dev = dev; regbase = devm_platform_ioremap_resource_byname(pdev, "control"); @@ -738,8 +737,6 @@ static int npcm_fiu_probe(struct platform_device *pdev) fiu->spix_mode = of_property_read_bool(dev->of_node, "nuvoton,spix-mode"); - platform_set_drvdata(pdev, fiu); - ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_DUAL | SPI_TX_QUAD; ctrl->setup = npcm_fiu_setup; @@ -750,10 +747,6 @@ static int npcm_fiu_probe(struct platform_device *pdev) return devm_spi_register_controller(dev, ctrl); } -static void npcm_fiu_remove(struct platform_device *pdev) -{ -} - MODULE_DEVICE_TABLE(of, npcm_fiu_dt_ids); static struct platform_driver npcm_fiu_driver = { @@ -763,7 +756,6 @@ static struct platform_driver npcm_fiu_driver = { .of_match_table = npcm_fiu_dt_ids, }, .probe = npcm_fiu_probe, - .remove = npcm_fiu_remove, }; module_platform_driver(npcm_fiu_driver); From 84d31bb1f6256eea0db6cf64a3c7a53145f92bb9 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:00 +0200 Subject: [PATCH 061/115] spi: amlogic-spisg: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like clocks during driver unbind. Fixes: cef9991e04ae ("spi: Add Amlogic SPISG driver") Cc: stable@vger.kernel.org # 6.17: b8db95529979 Cc: stable@vger.kernel.org # 6.17 Cc: Sunny Luo Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260409120419.388546-2-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-amlogic-spisg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-amlogic-spisg.c b/drivers/spi/spi-amlogic-spisg.c index da8ec35115da..19c5eba412ef 100644 --- a/drivers/spi/spi-amlogic-spisg.c +++ b/drivers/spi/spi-amlogic-spisg.c @@ -800,7 +800,7 @@ static int aml_spisg_probe(struct platform_device *pdev) goto out_clk; } - ret = devm_spi_register_controller(dev, ctlr); + ret = spi_register_controller(ctlr); if (ret) { dev_err(&pdev->dev, "spi controller registration failed\n"); goto out_clk; @@ -823,6 +823,8 @@ static void aml_spisg_remove(struct platform_device *pdev) { struct spisg_device *spisg = platform_get_drvdata(pdev); + spi_unregister_controller(spisg->controller); + if (!pm_runtime_suspended(&pdev->dev)) { pinctrl_pm_select_sleep_state(&spisg->pdev->dev); clk_disable_unprepare(spisg->core); From 1044e5a4ccd57bf5a64f90100a321b498e0267a2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:01 +0200 Subject: [PATCH 062/115] spi: aspeed-smc: fix controller deregistration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure to deregister the controller before disabling it to allow SPI device drivers to do I/O during deregistration. Fixes: e3228ed92893 ("spi: spi-mem: Convert Aspeed SMC driver to spi-mem") Cc: stable@vger.kernel.org # 5.19 Cc: Cédric Le Goater Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260409120419.388546-3-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-aspeed-smc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c index 9c286e534bf0..c21323e07d3c 100644 --- a/drivers/spi/spi-aspeed-smc.c +++ b/drivers/spi/spi-aspeed-smc.c @@ -972,7 +972,7 @@ static int aspeed_spi_probe(struct platform_device *pdev) return -ENOMEM; aspi = spi_controller_get_devdata(ctlr); - platform_set_drvdata(pdev, aspi); + platform_set_drvdata(pdev, ctlr); aspi->data = data; aspi->dev = dev; @@ -1021,7 +1021,7 @@ static int aspeed_spi_probe(struct platform_device *pdev) return ret; } - ret = devm_spi_register_controller(dev, ctlr); + ret = spi_register_controller(ctlr); if (ret) dev_err(&pdev->dev, "spi_register_controller failed\n"); @@ -1030,7 +1030,10 @@ static int aspeed_spi_probe(struct platform_device *pdev) static void aspeed_spi_remove(struct platform_device *pdev) { - struct aspeed_spi *aspi = platform_get_drvdata(pdev); + struct spi_controller *ctlr = platform_get_drvdata(pdev); + struct aspeed_spi *aspi = spi_controller_get_devdata(ctlr); + + spi_unregister_controller(ctlr); aspeed_spi_enable(aspi, false); } From 9acecc9bcff058eaef40fd7a4c3650e88b06b220 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:02 +0200 Subject: [PATCH 063/115] spi: at91-usart: fix controller deregistration Make sure to deregister the controller before disabling and releasing underlying resources like clocks and DMA during driver unbind. Fixes: e1892546ff66 ("spi: at91-usart: Add driver for at91-usart as SPI") Cc: stable@vger.kernel.org # 4.20 Cc: Radu Pirea Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260409120419.388546-4-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-at91-usart.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-at91-usart.c b/drivers/spi/spi-at91-usart.c index 76eb3ba75ab1..79edc1cd13c0 100644 --- a/drivers/spi/spi-at91-usart.c +++ b/drivers/spi/spi-at91-usart.c @@ -556,7 +556,7 @@ static int at91_usart_spi_probe(struct platform_device *pdev) spin_lock_init(&aus->lock); init_completion(&aus->xfer_completion); - ret = devm_spi_register_controller(&pdev->dev, controller); + ret = spi_register_controller(controller); if (ret) goto at91_usart_fail_register_controller; @@ -634,8 +634,14 @@ static void at91_usart_spi_remove(struct platform_device *pdev) struct spi_controller *ctlr = platform_get_drvdata(pdev); struct at91_usart_spi *aus = spi_controller_get_devdata(ctlr); + spi_controller_get(ctlr); + + spi_unregister_controller(ctlr); + at91_usart_spi_release_dma(ctlr); clk_disable_unprepare(aus->clk); + + spi_controller_put(ctlr); } static const struct dev_pm_ops at91_usart_spi_pm_ops = { From 8d4de97e83520be89d0ff40610ca633b3963a7de Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:03 +0200 Subject: [PATCH 064/115] spi: atmel: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like clocks during driver unbind. Fixes: 754ce4f29937 ("[PATCH] SPI: atmel_spi driver") Cc: stable@vger.kernel.org # 2.6.21 Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260409120419.388546-5-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-atmel.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 445d645585bf..42db85d7ff8e 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1654,7 +1654,7 @@ static int atmel_spi_probe(struct platform_device *pdev) pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) goto out_free_dma; @@ -1688,8 +1688,12 @@ static void atmel_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct atmel_spi *as = spi_controller_get_devdata(host); + spi_controller_get(host); + pm_runtime_get_sync(&pdev->dev); + spi_unregister_controller(host); + /* reset the hardware and block queue progress */ if (as->use_dma) { atmel_spi_stop_dma(host); @@ -1716,6 +1720,8 @@ static void atmel_spi_remove(struct platform_device *pdev) pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + + spi_controller_put(host); } static int atmel_spi_runtime_suspend(struct device *dev) From c39e65a4e3b8e764efed0b2f5152a1a8547b80fd Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:04 +0200 Subject: [PATCH 065/115] spi: bcm63xx: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like clocks during driver unbind. Fixes: b42dfed83d95 ("spi: add Broadcom BCM63xx SPI controller driver") Cc: stable@vger.kernel.org # 3.4 Cc: Florian Fainelli Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260409120419.388546-6-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 47266bb23a33..40cd7efc4b54 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -602,7 +602,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) goto out_clk_disable; /* register and we are done */ - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(dev, "spi register failed\n"); goto out_clk_disable; @@ -625,11 +625,17 @@ static void bcm63xx_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct bcm63xx_spi *bs = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + /* reset spi block */ bcm_spi_writeb(bs, 0, SPI_INT_MASK); /* HW shutdown */ clk_disable_unprepare(bs->clk); + + spi_controller_put(host); } static int bcm63xx_spi_suspend(struct device *dev) From ab837c51899d7595c1165a45dfb631facad49461 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:05 +0200 Subject: [PATCH 066/115] spi: bcm63xx-hsspi: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like interrupts during driver unbind to allow SPI drivers to do I/O during deregistration. Note that clocks were also disabled before the recent commit e532e21a246d ("spi: bcm63xx-hsspi: Simplify clock handling with devm_clk_get_enabled()"). Fixes: 7d255695804f ("spi/bcm63xx-hsspi: use devm_register_master()") Cc: stable@vger.kernel.org # 3.14 Cc: Jonas Gorski Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260409120419.388546-7-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx-hsspi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index 266eabd3715b..e935e8ab9cfd 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -857,7 +857,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) } /* register and we are done */ - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) goto out_sysgroup_disable; @@ -880,9 +880,15 @@ static void bcm63xx_hsspi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + /* reset the hardware and block queue progress */ __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); sysfs_remove_group(&pdev->dev.kobj, &bcm63xx_hsspi_group); + + spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP From c3d97c3320b9a1ebbd6119857341be034f7b3efc Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:06 +0200 Subject: [PATCH 067/115] spi: bcmbca-hsspi: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like interrupts during driver unbind to allow SPI drivers to do I/O during deregistration. Note that clocks were also disabled before the recent commit e532e21a246d ("spi: bcm63xx-hsspi: Simplify clock handling with devm_clk_get_enabled()"). Fixes: a38a2233f23b ("spi: bcmbca-hsspi: Add driver for newer HSSPI controller") Cc: stable@vger.kernel.org # 6.3: deb269e0394f Cc: stable@vger.kernel.org # 6.3 Cc: William Zhang Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260409120419.388546-8-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-bcmbca-hsspi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-bcmbca-hsspi.c b/drivers/spi/spi-bcmbca-hsspi.c index 2e22345115fd..09c1472ae4fa 100644 --- a/drivers/spi/spi-bcmbca-hsspi.c +++ b/drivers/spi/spi-bcmbca-hsspi.c @@ -538,7 +538,7 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev) return dev_err_probe(dev, ret, "couldn't register sysfs group\n"); /* register and we are done */ - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) goto out_sysgroup_disable; @@ -556,6 +556,8 @@ static void bcmbca_hsspi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct bcmbca_hsspi *bs = spi_controller_get_devdata(host); + spi_unregister_controller(host); + /* reset the hardware and block queue progress */ __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); sysfs_remove_group(&pdev->dev.kobj, &bcmbca_hsspi_group); From 3c49a4d8799bee423a80f392ba95b26af8e9ab91 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:07 +0200 Subject: [PATCH 068/115] spi: octeon: fix controller deregistration Make sure to deregister the controller before disabling it to avoid hanging or leaking resources associated with the queue when the queue is non-empty. Fixes: 22ad2d8df77d ("spi: octeon: use devm_spi_register_master()") Cc: stable@vger.kernel.org # 3.13 Cc: Jingoo Han Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260409120419.388546-9-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-cavium-octeon.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-cavium-octeon.c b/drivers/spi/spi-cavium-octeon.c index 155085a053a1..b95bfa6a3013 100644 --- a/drivers/spi/spi-cavium-octeon.c +++ b/drivers/spi/spi-cavium-octeon.c @@ -54,7 +54,7 @@ static int octeon_spi_probe(struct platform_device *pdev) host->bits_per_word_mask = SPI_BPW_MASK(8); host->max_speed_hz = OCTEON_SPI_MAX_CLOCK_HZ; - err = devm_spi_register_controller(&pdev->dev, host); + err = spi_register_controller(host); if (err) { dev_err(&pdev->dev, "register host failed: %d\n", err); goto fail; @@ -73,8 +73,14 @@ static void octeon_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct octeon_spi *p = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + /* Clear the CSENA* and put everything in a known state. */ writeq(0, p->register_base + OCTEON_SPI_CFG(p)); + + spi_controller_put(host); } static const struct of_device_id octeon_spi_match[] = { From dbb6b01267c0c866eaac4019cec19f414beec61d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:08 +0200 Subject: [PATCH 069/115] spi: cavium-thunderx: fix controller deregistration Make sure to deregister the controller before disabling it to avoid hanging or leaking resources associated with the queue when the queue non-empty. Fixes: 7347a6c7af8d ("spi: octeon: Add ThunderX driver") Cc: stable@vger.kernel.org # 4.9 Cc: Jan Glauber Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260409120419.388546-10-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-cavium-thunderx.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-cavium-thunderx.c b/drivers/spi/spi-cavium-thunderx.c index 99aac40a1bba..f1a9aa696c87 100644 --- a/drivers/spi/spi-cavium-thunderx.c +++ b/drivers/spi/spi-cavium-thunderx.c @@ -70,7 +70,7 @@ static int thunderx_spi_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, host); - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) goto error; @@ -90,8 +90,14 @@ static void thunderx_spi_remove(struct pci_dev *pdev) if (!p) return; + spi_controller_get(host); + + spi_unregister_controller(host); + /* Put everything in a known state. */ writeq(0, p->register_base + OCTEON_SPI_CFG(p)); + + spi_controller_put(host); } static const struct pci_device_id thunderx_spi_pci_id_table[] = { From e7c510e192ff2a1264d999575eea39a506424264 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:09 +0200 Subject: [PATCH 070/115] spi: coldfire-qspi: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like clocks (via runtime pm) during driver unbind. Fixes: 34b8c6617366 ("spi: Add Freescale/Motorola Coldfire QSPI driver") Cc: stable@vger.kernel.org # 2.6.34 Cc: Steven King Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260409120419.388546-11-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-coldfire-qspi.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index fdf37636cb9f..b45f44de85dc 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -410,9 +410,9 @@ static int mcfqspi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, host); pm_runtime_enable(&pdev->dev); - status = devm_spi_register_controller(&pdev->dev, host); + status = spi_register_controller(host); if (status) { - dev_dbg(&pdev->dev, "devm_spi_register_controller failed\n"); + dev_dbg(&pdev->dev, "failed to register controller\n"); goto fail1; } @@ -436,11 +436,17 @@ static void mcfqspi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct mcfqspi *mcfqspi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_disable(&pdev->dev); /* disable the hardware (set the baud rate to 0) */ mcfqspi_wr_qmr(mcfqspi, MCFQSPI_QMR_MSTR); mcfqspi_cs_teardown(mcfqspi); + + spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP From c353020fbfa8514ee91a6de2d88de4e5edca5803 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:10 +0200 Subject: [PATCH 071/115] spi: dln2: fix controller deregistration Make sure to deregister the controller before disabling it to allow SPI device drivers to do I/O during deregistration. Fixes: 3d8c0d749da3 ("spi: add support for DLN-2 USB-SPI adapter") Cc: stable@vger.kernel.org # 4.0 Cc: Laurentiu Palcu Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260409120419.388546-12-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-dln2.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-dln2.c b/drivers/spi/spi-dln2.c index d90282960ab6..392f0d05f508 100644 --- a/drivers/spi/spi-dln2.c +++ b/drivers/spi/spi-dln2.c @@ -758,7 +758,7 @@ static int dln2_spi_probe(struct platform_device *pdev) pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret < 0) { dev_err(&pdev->dev, "Failed to register host\n"); goto exit_register; @@ -783,10 +783,16 @@ static void dln2_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct dln2_spi *dln2 = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_disable(&pdev->dev); if (dln2_spi_enable(dln2, false) < 0) dev_err(&pdev->dev, "Failed to disable SPI module\n"); + + spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP From f4838934b695a58eda0833583cb8028e73a19529 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:11 +0200 Subject: [PATCH 072/115] spi: ep93xx: fix controller deregistration Make sure to deregister the controller before releasing underlying resources like DMA during driver unbind. Fixes: 011f23a3c2f2 ("spi/ep93xx: implemented driver for Cirrus EP93xx SPI controller") Cc: stable@vger.kernel.org # 2.6.35 Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260409120419.388546-13-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 90d5f3ea6508..db50018050e5 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -689,7 +689,7 @@ static int ep93xx_spi_probe(struct platform_device *pdev) /* make sure that the hardware is disabled */ writel(0, espi->mmio + SSPCR1); - error = devm_spi_register_controller(&pdev->dev, host); + error = spi_register_controller(host); if (error) { dev_err(&pdev->dev, "failed to register SPI host\n"); goto fail_free_dma; @@ -713,7 +713,13 @@ static void ep93xx_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct ep93xx_spi *espi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + ep93xx_spi_release_dma(espi); + + spi_controller_put(host); } static const struct of_device_id ep93xx_spi_of_ids[] = { From e506a700a7ad229f5c8f01f4b8350119cccb4158 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:12 +0200 Subject: [PATCH 073/115] spi: fsl-espi: fix controller deregistration Make sure to deregister the controller before disabling runtime PM (which can leave the controller disabled) to allow SPI device drivers to do I/O during deregistration. Fixes: e9abb4db8d10 ("spi: fsl-espi: add runtime PM") Cc: stable@vger.kernel.org # 4.3 Cc: Heiner Kallweit Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260409120419.388546-14-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 56270f8fdc17..45b9974ae911 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -718,7 +718,7 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem, pm_runtime_enable(dev); pm_runtime_get_sync(dev); - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret < 0) goto err_pm; @@ -782,7 +782,15 @@ static int of_fsl_espi_probe(struct platform_device *ofdev) static void of_fsl_espi_remove(struct platform_device *dev) { + struct spi_controller *host = platform_get_drvdata(dev); + + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_disable(&dev->dev); + + spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP From fc3a83b0d9c16b941c9028f5a8db9541dce4ddf2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:14 +0200 Subject: [PATCH 074/115] spi: img-spfi: fix controller deregistration Make sure to deregister the controller before disabling and releasing underlying resources like clocks and DMA during driver unbind. Fixes: deba25800a12 ("spi: Add driver for IMG SPFI controller") Cc: stable@vger.kernel.org # 3.19 Cc: Andrew Bresticker Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260409120419.388546-16-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-img-spfi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index 902fb64815c9..57625a3ce2f2 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -643,7 +643,7 @@ static int img_spfi_probe(struct platform_device *pdev) pm_runtime_set_active(spfi->dev); pm_runtime_enable(spfi->dev); - ret = devm_spi_register_controller(spfi->dev, host); + ret = spi_register_controller(host); if (ret) goto disable_pm; @@ -669,6 +669,10 @@ static void img_spfi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct img_spfi *spfi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + if (spfi->tx_ch) dma_release_channel(spfi->tx_ch); if (spfi->rx_ch) @@ -679,6 +683,8 @@ static void img_spfi_remove(struct platform_device *pdev) clk_disable_unprepare(spfi->spfi_clk); clk_disable_unprepare(spfi->sys_clk); } + + spi_controller_put(host); } #ifdef CONFIG_PM From b99206710d032c16b7f8b75e4bc18414d8e4b9f4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:15 +0200 Subject: [PATCH 075/115] spi: lantiq-ssc: fix controller deregistration Make sure to deregister the controller before releasing underlying resources like clocks during driver unbind. Fixes: 17f84b793c01 ("spi: lantiq-ssc: add support for Lantiq SSC SPI controller") Cc: stable@vger.kernel.org # 4.11 Cc: Hauke Mehrtens Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260409120419.388546-17-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-lantiq-ssc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-lantiq-ssc.c b/drivers/spi/spi-lantiq-ssc.c index f83cb63c9d0c..75b9af8cb5db 100644 --- a/drivers/spi/spi-lantiq-ssc.c +++ b/drivers/spi/spi-lantiq-ssc.c @@ -994,7 +994,7 @@ static int lantiq_ssc_probe(struct platform_device *pdev) "Lantiq SSC SPI controller (Rev %i, TXFS %u, RXFS %u, DMA %u)\n", revision, spi->tx_fifo_size, spi->rx_fifo_size, supports_dma); - err = devm_spi_register_controller(dev, host); + err = spi_register_controller(host); if (err) { dev_err(dev, "failed to register spi host\n"); goto err_wq_destroy; @@ -1016,6 +1016,10 @@ static void lantiq_ssc_remove(struct platform_device *pdev) { struct lantiq_ssc_spi *spi = platform_get_drvdata(pdev); + spi_controller_get(spi->host); + + spi_unregister_controller(spi->host); + lantiq_ssc_writel(spi, 0, LTQ_SPI_IRNEN); lantiq_ssc_writel(spi, 0, LTQ_SPI_CLC); rx_fifo_flush(spi); @@ -1024,6 +1028,8 @@ static void lantiq_ssc_remove(struct platform_device *pdev) destroy_workqueue(spi->wq); clk_put(spi->fpi_clk); + + spi_controller_put(spi->host); } static struct platform_driver lantiq_ssc_driver = { From 77953c76bec9af4191f8692a10225dd816208718 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:16 +0200 Subject: [PATCH 076/115] spi: meson-spicc: fix controller deregistration Make sure to deregister the controller before disabling it to allow SPI device drivers to do I/O during deregistration. Fixes: 454fa271bc4e ("spi: Add Meson SPICC driver") Cc: stable@vger.kernel.org # 4.13 Cc: Neil Armstrong Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260409120419.388546-18-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-meson-spicc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c index 57768da3205d..b80f9f457b66 100644 --- a/drivers/spi/spi-meson-spicc.c +++ b/drivers/spi/spi-meson-spicc.c @@ -1081,7 +1081,7 @@ static int meson_spicc_probe(struct platform_device *pdev) } } - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&pdev->dev, "spi registration failed\n"); goto out_host; @@ -1099,8 +1099,14 @@ static void meson_spicc_remove(struct platform_device *pdev) { struct meson_spicc_device *spicc = platform_get_drvdata(pdev); + spi_controller_get(spicc->host); + + spi_unregister_controller(spicc->host); + /* Disable SPI */ writel(0, spicc->base + SPICC_CONREG); + + spi_controller_put(spicc->host); } static const struct meson_spicc_data meson_spicc_gx_data = { From e6464140d439f2d42f072eb422a5b1fec470c5a6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:17 +0200 Subject: [PATCH 077/115] spi: microchip-core-qspi: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like interrupts during driver unbind. Fixes: 8596124c4c1b ("spi: microchip-core-qspi: Add support for microchip fpga qspi controllers") Cc: stable@vger.kernel.org # 6.1 Cc: Naga Sureshkumar Relli Signed-off-by: Johan Hovold Acked-by: Conor Dooley Link: https://patch.msgid.link/20260409120419.388546-19-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-microchip-core-qspi.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-microchip-core-qspi.c b/drivers/spi/spi-microchip-core-qspi.c index aafe6cbf2aea..eab059fb0bc2 100644 --- a/drivers/spi/spi-microchip-core-qspi.c +++ b/drivers/spi/spi-microchip-core-qspi.c @@ -692,7 +692,7 @@ static int mchp_coreqspi_probe(struct platform_device *pdev) return -ENOMEM; qspi = spi_controller_get_devdata(ctlr); - platform_set_drvdata(pdev, qspi); + platform_set_drvdata(pdev, ctlr); qspi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(qspi->regs)) @@ -732,7 +732,7 @@ static int mchp_coreqspi_probe(struct platform_device *pdev) ctlr->num_chipselect = 2; ctlr->use_gpio_descriptors = true; - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret) return dev_err_probe(&pdev->dev, ret, "spi_register_controller failed\n"); @@ -742,9 +742,13 @@ static int mchp_coreqspi_probe(struct platform_device *pdev) static void mchp_coreqspi_remove(struct platform_device *pdev) { - struct mchp_coreqspi *qspi = platform_get_drvdata(pdev); - u32 control = readl_relaxed(qspi->regs + REG_CONTROL); + struct spi_controller *ctlr = platform_get_drvdata(pdev); + struct mchp_coreqspi *qspi = spi_controller_get_devdata(ctlr); + u32 control; + spi_unregister_controller(ctlr); + + control = readl_relaxed(qspi->regs + REG_CONTROL); mchp_coreqspi_disable_ints(qspi); control &= ~CONTROL_ENABLE; writel_relaxed(control, qspi->regs + REG_CONTROL); From d00d722ebad46cf7a9886684f26a26337b5ee3f4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:18 +0200 Subject: [PATCH 078/115] spi: microchip-core-spi: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like interrupts during driver unbind. Fixes: 059f545832be ("spi: add support for microchip "soft" spi controller") Cc: stable@vger.kernel.org # 6.19 Cc: Prajna Rajendra Kumar Signed-off-by: Johan Hovold Acked-by: Conor Dooley Link: https://patch.msgid.link/20260409120419.388546-20-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-microchip-core-spi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-microchip-core-spi.c b/drivers/spi/spi-microchip-core-spi.c index a4c128ae391b..be01c178e2b0 100644 --- a/drivers/spi/spi-microchip-core-spi.c +++ b/drivers/spi/spi-microchip-core-spi.c @@ -384,7 +384,7 @@ static int mchp_corespi_probe(struct platform_device *pdev) mchp_corespi_init(host, spi); - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) { mchp_corespi_disable_ints(spi); mchp_corespi_disable(spi); @@ -399,6 +399,8 @@ static void mchp_corespi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct mchp_corespi *spi = spi_controller_get_devdata(host); + spi_unregister_controller(host); + mchp_corespi_disable_ints(spi); mchp_corespi_disable(spi); } From 573c7db8fce91a1b07dd64a260bb44b9e6d05943 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Apr 2026 14:04:19 +0200 Subject: [PATCH 079/115] spi: mpfs: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like interrupts during driver unbind. Fixes: 9ac8d17694b6 ("spi: add support for microchip fpga spi controllers") Cc: stable@vger.kernel.org # 6.0 Cc: Conor Dooley Signed-off-by: Johan Hovold Acked-by: Conor Dooley Link: https://patch.msgid.link/20260409120419.388546-21-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-mpfs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-mpfs.c b/drivers/spi/spi-mpfs.c index 64d15a6188ac..989a379b0700 100644 --- a/drivers/spi/spi-mpfs.c +++ b/drivers/spi/spi-mpfs.c @@ -574,7 +574,7 @@ static int mpfs_spi_probe(struct platform_device *pdev) mpfs_spi_init(host, spi); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { mpfs_spi_disable_ints(spi); mpfs_spi_disable(spi); @@ -592,6 +592,8 @@ static void mpfs_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct mpfs_spi *spi = spi_controller_get_devdata(host); + spi_unregister_controller(host); + mpfs_spi_disable_ints(spi); mpfs_spi_disable(spi); } From 9b7abfed4c3754062d1f3ffd452e65a38667f586 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 08:47:49 +0200 Subject: [PATCH 080/115] spi: fsl: fix controller deregistration Make sure to deregister the controller before releasing underlying resources like DMA during driver unbind. Fixes: 4178b6b1b595 ("spi: fsl-(e)spi: migrate to using devm_ functions to simplify cleanup") Cc: stable@vger.kernel.org # 4.3 Cc: Heiner Kallweit Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410064749.496888-1-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-spi.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index bf3fc3ce0cc2..1252c41c206f 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -614,7 +614,7 @@ static struct spi_controller *fsl_spi_probe(struct device *dev, mpc8xxx_spi_write_reg(®_base->mode, regval); - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret < 0) goto err_probe; @@ -705,7 +705,13 @@ static void of_fsl_spi_remove(struct platform_device *ofdev) struct spi_controller *host = platform_get_drvdata(ofdev); struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + fsl_spi_cpm_free(mpc8xxx_spi); + + spi_controller_put(host); } static struct platform_driver of_fsl_spi_driver = { @@ -751,7 +757,13 @@ static void plat_mpc8xxx_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + fsl_spi_cpm_free(mpc8xxx_spi); + + spi_controller_put(host); } MODULE_ALIAS("platform:mpc8xxx_spi"); From 4e292cbf3890657db2f2692942cb0f168c80167e Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 10 Apr 2026 09:05:15 +0100 Subject: [PATCH 081/115] spi: rzv2h-rspi: Fix max_speed_hz advertising prohibited bit rate On RZ/V2H(P), RZ/G3E and RZ/G3L, RSPI_n_TCLK is fixed at 200MHz. The max_speed_hz was computed using clk_round_rate(tclk, ULONG_MAX) with SPR=0 and BRDV=0, resulting in 100Mbps - the exact combination prohibited on these SoCs. This could cause the SPI framework to request a speed that rzv2h_rspi_find_rate_fixed() would skip, potentially leading to a clock selection failure. On RZ/T2H and RZ/N2H the max_speed_hz was correctly calculated as 50Mbps for both the variable PCLKSPIn and fixed PCLK clock sources. Since the maximum supported bit rate is 50Mbps across all supported SoC variants, replace the clk_round_rate() based calculation with a define RSPI_MAX_SPEED_HZ set to 50MHz and use it directly for max_speed_hz. Signed-off-by: Lad Prabhakar Link: https://patch.msgid.link/20260410080517.2405700-2-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Mark Brown --- drivers/spi/spi-rzv2h-rspi.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-rzv2h-rspi.c b/drivers/spi/spi-rzv2h-rspi.c index 23f0e92ae208..15270f19c69c 100644 --- a/drivers/spi/spi-rzv2h-rspi.c +++ b/drivers/spi/spi-rzv2h-rspi.c @@ -77,6 +77,8 @@ #define RSPI_RESET_NUM 2 +#define RSPI_MAX_SPEED_HZ 50000000 + struct rzv2h_rspi_best_clock { struct clk *clk; unsigned long clk_rate; @@ -771,13 +773,7 @@ static int rzv2h_rspi_probe(struct platform_device *pdev) RSPI_SPBR_SPR_MAX, RSPI_SPCMD_BRDV_MAX); - tclk_rate = clk_round_rate(rspi->tclk, ULONG_MAX); - if (tclk_rate < 0) - return tclk_rate; - - controller->max_speed_hz = rzv2h_rspi_calc_bitrate(tclk_rate, - RSPI_SPBR_SPR_MIN, - RSPI_SPCMD_BRDV_MIN); + controller->max_speed_hz = RSPI_MAX_SPEED_HZ; controller->dma_tx = devm_dma_request_chan(dev, "tx"); if (IS_ERR(controller->dma_tx)) { From 0335767dd8e7ade8a8e3028d08c4621515d47388 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 10 Apr 2026 09:05:16 +0100 Subject: [PATCH 082/115] spi: rzv2h-rspi: Fix invalid SPR=0/BRDV=0 clock configuration The combination of SPR=0 and BRDV=0 results in the minimum division ratio of 2, producing the maximum possible bit rate for a given clock source. This combination is not supported in two cases: - On RZ/G3E, RZ/G3L, RZ/V2H(P) and RZ/V2N, RSPI_n_TCLK is fixed at 200MHz, which would yield 100Mbps. The next hardware manual update will explicitly state that since the maximum frequency of the RSPICKn clock signal is 50MHz, settings with N=0 and n=0 resulting in 100Mbps are prohibited. - On RZ/T2H and RZ/N2H, when PCLK (125MHz) is used as the clock source, SPR=0 and BRDV=0 is explicitly listed as unsupported in the hardware manual (Table 36.7). Skip the SPR=0/BRDV=0 combination in rzv2h_rspi_find_rate_fixed() to prevent the driver from selecting an invalid clock configuration on the affected SoCs. Additionally, remove the now redundant RSPI_SPBR_SPR_PCLK_MIN define which was previously set to 1 to work around the PCLK restriction, but was overly broad as it incorrectly blocked valid combinations such as SPR=0/BRDV=1 (31.25Mbps on PCLK=125MHz). Fixes: 8b61c8919dff ("spi: Add driver for the RZ/V2H(P) RSPI IP") Fixes: 1ce3e8adc7d0 ("spi: rzv2h-rspi: add support for using PCLK for transfer clock") Signed-off-by: Lad Prabhakar Link: https://patch.msgid.link/20260410080517.2405700-3-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Mark Brown --- drivers/spi/spi-rzv2h-rspi.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-rzv2h-rspi.c b/drivers/spi/spi-rzv2h-rspi.c index 15270f19c69c..f62223e106c0 100644 --- a/drivers/spi/spi-rzv2h-rspi.c +++ b/drivers/spi/spi-rzv2h-rspi.c @@ -50,7 +50,6 @@ /* Register SPBR */ #define RSPI_SPBR_SPR_MIN 0 -#define RSPI_SPBR_SPR_PCLK_MIN 1 #define RSPI_SPBR_SPR_MAX 255 /* Register SPCMD */ @@ -535,6 +534,17 @@ static void rzv2h_rspi_find_rate_fixed(struct clk *clk, u32 hz, for (brdv = RSPI_SPCMD_BRDV_MIN; brdv <= RSPI_SPCMD_BRDV_MAX; brdv++) { spr = DIV_ROUND_UP(clk_rate, hz * (1 << (brdv + 1))); spr--; + /* + * Skip SPR=0 and BRDV=0 as it is not a valid combination: + * - On RZ/G3E, RZ/G3L, RZ/V2H(P) and RZ/V2N, RSPI_n_TCLK is + * fixed at 200MHz and SPR=0 and BRDV=0 results in the maximum + * bit rate of 100Mbps which is prohibited. + * - On RZ/T2H and RZ/N2H, when PCLK (125MHz) is used as + * the clock source, SPR=0 and BRDV=0 is explicitly listed + * as unsupported in the hardware manual (Table 36.7). + */ + if (!spr && !brdv) + continue; if (spr >= spr_min && spr <= spr_max) goto clock_found; } @@ -568,12 +578,8 @@ static u32 rzv2h_rspi_setup_clock(struct rzv2h_rspi_priv *rspi, u32 hz) rspi->info->find_tclk_rate(rspi->tclk, hz, RSPI_SPBR_SPR_MIN, RSPI_SPBR_SPR_MAX, &best_clock); - /* - * T2H and N2H can also use PCLK as a source, which is 125MHz, but not - * when both SPR and BRDV are 0. - */ if (best_clock.error && rspi->info->find_pclk_rate) - rspi->info->find_pclk_rate(rspi->pclk, hz, RSPI_SPBR_SPR_PCLK_MIN, + rspi->info->find_pclk_rate(rspi->pclk, hz, RSPI_SPBR_SPR_MIN, RSPI_SPBR_SPR_MAX, &best_clock); if (!best_clock.clk_rate) From c958bb67b2dfd87b09d725a60162d13674fc5fd9 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 10 Apr 2026 09:05:17 +0100 Subject: [PATCH 083/115] spi: rzv2h-rspi: Simplify clock rate search function signatures The spr_min and spr_max parameters passed to rzv2h_rspi_find_rate_variable() and rzv2h_rspi_find_rate_fixed() were always called with RSPI_SPBR_SPR_MIN and RSPI_SPBR_SPR_MAX respectively. There is no need to pass these as parameters since the valid SPR range is fixed by the hardware. Signed-off-by: Lad Prabhakar Link: https://patch.msgid.link/20260410080517.2405700-4-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Mark Brown --- drivers/spi/spi-rzv2h-rspi.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/drivers/spi/spi-rzv2h-rspi.c b/drivers/spi/spi-rzv2h-rspi.c index f62223e106c0..56f2689bb048 100644 --- a/drivers/spi/spi-rzv2h-rspi.c +++ b/drivers/spi/spi-rzv2h-rspi.c @@ -88,9 +88,9 @@ struct rzv2h_rspi_best_clock { }; struct rzv2h_rspi_info { - void (*find_tclk_rate)(struct clk *clk, u32 hz, u8 spr_min, u8 spr_max, + void (*find_tclk_rate)(struct clk *clk, u32 hz, struct rzv2h_rspi_best_clock *best_clk); - void (*find_pclk_rate)(struct clk *clk, u32 hz, u8 spr_low, u8 spr_high, + void (*find_pclk_rate)(struct clk *clk, u32 hz, struct rzv2h_rspi_best_clock *best_clk); const char *tclk_name; unsigned int fifo_size; @@ -413,7 +413,6 @@ static inline u32 rzv2h_rspi_calc_bitrate(unsigned long tclk_rate, u8 spr, } static void rzv2h_rspi_find_rate_variable(struct clk *clk, u32 hz, - u8 spr_min, u8 spr_max, struct rzv2h_rspi_best_clock *best) { long clk_rate, clk_min_rate, clk_max_rate; @@ -464,7 +463,7 @@ static void rzv2h_rspi_find_rate_variable(struct clk *clk, u32 hz, * minimum SPR that is in the valid range. */ min_rate_spr = DIV_ROUND_CLOSEST(clk_min_rate, rate_div) - 1; - if (min_rate_spr > spr_max) + if (min_rate_spr > RSPI_SPBR_SPR_MAX) continue; /* @@ -474,14 +473,14 @@ static void rzv2h_rspi_find_rate_variable(struct clk *clk, u32 hz, * maximum SPR that is in the valid range. */ max_rate_spr = DIV_ROUND_CLOSEST(clk_max_rate, rate_div) - 1; - if (max_rate_spr < spr_min) + if (max_rate_spr < RSPI_SPBR_SPR_MIN) break; - if (min_rate_spr < spr_min) - min_rate_spr = spr_min; + if (min_rate_spr < RSPI_SPBR_SPR_MIN) + min_rate_spr = RSPI_SPBR_SPR_MIN; - if (max_rate_spr > spr_max) - max_rate_spr = spr_max; + if (max_rate_spr > RSPI_SPBR_SPR_MAX) + max_rate_spr = RSPI_SPBR_SPR_MAX; for (spr = min_rate_spr; spr <= max_rate_spr; spr++) { clk_rate = (spr + 1) * rate_div; @@ -512,7 +511,6 @@ static void rzv2h_rspi_find_rate_variable(struct clk *clk, u32 hz, } static void rzv2h_rspi_find_rate_fixed(struct clk *clk, u32 hz, - u8 spr_min, u8 spr_max, struct rzv2h_rspi_best_clock *best) { unsigned long clk_rate; @@ -545,7 +543,7 @@ static void rzv2h_rspi_find_rate_fixed(struct clk *clk, u32 hz, */ if (!spr && !brdv) continue; - if (spr >= spr_min && spr <= spr_max) + if (spr >= RSPI_SPBR_SPR_MIN && spr <= RSPI_SPBR_SPR_MAX) goto clock_found; } @@ -575,12 +573,10 @@ static u32 rzv2h_rspi_setup_clock(struct rzv2h_rspi_priv *rspi, u32 hz) }; int ret; - rspi->info->find_tclk_rate(rspi->tclk, hz, RSPI_SPBR_SPR_MIN, - RSPI_SPBR_SPR_MAX, &best_clock); + rspi->info->find_tclk_rate(rspi->tclk, hz, &best_clock); if (best_clock.error && rspi->info->find_pclk_rate) - rspi->info->find_pclk_rate(rspi->pclk, hz, RSPI_SPBR_SPR_MIN, - RSPI_SPBR_SPR_MAX, &best_clock); + rspi->info->find_pclk_rate(rspi->pclk, hz, &best_clock); if (!best_clock.clk_rate) return -EINVAL; From 5b94c94caafcad3c77cc6b1d213a93bf5dc0a98e Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Wed, 8 Apr 2026 06:45:43 -0700 Subject: [PATCH 084/115] spi: tegra210-quad: Fix false positive WARN on interrupt timeout with transfer complete The WARN_ON_ONCE/WARN_ON fired unconditionally on any completion timeout, including the recoverable case where the interrupt was lost but the hardware actually finished the transfer. This produced a noisy splat with a full call trace even though the driver successfully recovered via tegra_qspi_handle_timeout(). Since tegra210 uses threaded interrupts, the transfer completion can be signaled before the interrupt fires, making this false positive case common in practice. Almost all the hosts I sysadmin in my fleet produce the following splat: WARNING: CPU: 47 PID: 844 at drivers/spi/spi-tegra210-quad.c:1226 tegra_qspi_transfer_one_message+0x8a4/0xba8 .... tegra-qspi NVDA1513:00: QSPI interrupt timeout, but transfer complete Move WARN_ON_ONCE/WARN_ON to fire only on real unrecoverable timeouts, i.e., when tegra_qspi_handle_timeout() confirms the hardware did NOT complete. This makes the warning actionable instead of just polluting the metrics. Signed-off-by: Breno Leitao Link: https://patch.msgid.link/20260408-tegra_warn-v1-1-669a3bc74d77@debian.org Signed-off-by: Mark Brown --- drivers/spi/spi-tegra210-quad.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c index 7cca5578eba3..db28dd556484 100644 --- a/drivers/spi/spi-tegra210-quad.c +++ b/drivers/spi/spi-tegra210-quad.c @@ -1223,7 +1223,7 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, (&tqspi->xfer_completion, QSPI_DMA_TIMEOUT); - if (WARN_ON_ONCE(ret == 0)) { + if (ret == 0) { /* * Check if hardware completed the transfer * even though interrupt was lost or delayed. @@ -1232,6 +1232,7 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, ret = tegra_qspi_handle_timeout(tqspi); if (ret < 0) { /* Real timeout - clean up and fail */ + WARN_ON_ONCE(1); dev_err(tqspi->dev, "transfer timeout\n"); /* Abort transfer by resetting pio/dma bit */ @@ -1340,7 +1341,7 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, ret = wait_for_completion_timeout(&tqspi->xfer_completion, QSPI_DMA_TIMEOUT); - if (WARN_ON(ret == 0)) { + if (ret == 0) { /* * Check if hardware completed the transfer even though * interrupt was lost or delayed. If so, process the @@ -1349,6 +1350,7 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, ret = tegra_qspi_handle_timeout(tqspi); if (ret < 0) { /* Real timeout - clean up and fail */ + WARN_ON(1); dev_err(tqspi->dev, "transfer timeout\n"); if (tqspi->is_curr_dma_xfer) From 2ad30599cccc572ba2fc11010670eb6e01ea6bfc Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:31 +0200 Subject: [PATCH 085/115] spi: mt65xx: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like clocks during driver unbind. Fixes: a568231f4632 ("spi: mediatek: Add spi bus for Mediatek MT8173") Cc: stable@vger.kernel.org # 4.3: ace145802350 Cc: stable@vger.kernel.org # 4.3 Cc: Leilk Liu Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-2-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-mt65xx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 0368a26bca9a..96f8555be983 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -1325,7 +1325,7 @@ static int mtk_spi_probe(struct platform_device *pdev) pm_runtime_enable(dev); - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) { pm_runtime_disable(dev); return dev_err_probe(dev, ret, "failed to register host\n"); @@ -1340,6 +1340,8 @@ static void mtk_spi_remove(struct platform_device *pdev) struct mtk_spi *mdata = spi_controller_get_devdata(host); int ret; + spi_unregister_controller(host); + cpu_latency_qos_remove_request(&mdata->qos_request); if (mdata->use_spimem && !completion_done(&mdata->spimem_done)) complete(&mdata->spimem_done); From 76336f24934621db286cabb20b483773ee01dcaa Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:32 +0200 Subject: [PATCH 086/115] spi: mtk-nor: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like clocks during driver unbind. Fixes: 881d1ee9fe81 ("spi: add support for mediatek spi-nor controller") Cc: stable@vger.kernel.org # 5.7 Cc: Chuanhong Guo Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-3-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-mtk-nor.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c index 1e5ec0840174..74f34537b02c 100644 --- a/drivers/spi/spi-mtk-nor.c +++ b/drivers/spi/spi-mtk-nor.c @@ -913,7 +913,7 @@ static int mtk_nor_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_get_noresume(&pdev->dev); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) goto err_probe; @@ -938,6 +938,8 @@ static void mtk_nor_remove(struct platform_device *pdev) struct spi_controller *ctlr = dev_get_drvdata(&pdev->dev); struct mtk_nor *sp = spi_controller_get_devdata(ctlr); + spi_unregister_controller(ctlr); + pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); From 8b0d0011af20fb547aa67a1cefbf320992fd5e92 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:33 +0200 Subject: [PATCH 087/115] spi: mxs: fix controller deregistration Make sure to deregister the controller before releasing underlying resources like DMA during driver unbind. Fixes: 33e195acf268 ("spi: mxs: use devm_spi_register_master()") Cc: stable@vger.kernel.org # 3.13 Cc: Jingoo Han Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-4-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index b3301c69e2de..0164e04d59a1 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -619,7 +619,7 @@ static int mxs_spi_probe(struct platform_device *pdev) if (ret) goto out_pm_runtime_put; - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&pdev->dev, "Cannot register SPI host, %d\n", ret); goto out_pm_runtime_put; @@ -650,11 +650,17 @@ static void mxs_spi_remove(struct platform_device *pdev) spi = spi_controller_get_devdata(host); ssp = &spi->ssp; + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) mxs_spi_runtime_suspend(&pdev->dev); dma_release_channel(ssp->dmach); + + spi_controller_put(host); } static struct platform_driver mxs_spi_driver = { From ebd81199e00e107980bf8c4d2c747ae50158f797 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:34 +0200 Subject: [PATCH 088/115] spi: npcm-pspi: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like clocks during driver unbind. Fixes: 2a22f1b30cee ("spi: npcm: add NPCM PSPI controller driver") Cc: stable@vger.kernel.org # 5.0 Cc: Tomer Maimon Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-5-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-npcm-pspi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-npcm-pspi.c b/drivers/spi/spi-npcm-pspi.c index e60b3cc398ec..cffef0a5977d 100644 --- a/drivers/spi/spi-npcm-pspi.c +++ b/drivers/spi/spi-npcm-pspi.c @@ -413,7 +413,7 @@ static int npcm_pspi_probe(struct platform_device *pdev) /* set to default clock rate */ npcm_pspi_set_baudrate(priv, NPCM_PSPI_DEFAULT_CLK); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) goto out_disable_clk; @@ -434,8 +434,14 @@ static void npcm_pspi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct npcm_pspi *priv = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + npcm_pspi_reset_hw(priv); clk_disable_unprepare(priv->clk); + + spi_controller_put(host); } static const struct of_device_id npcm_pspi_match[] = { From fb45f95c377e4a4bdece2c5e17643b459c9c13e7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:35 +0200 Subject: [PATCH 089/115] spi: omap2-mcspi: fix controller deregistration Make sure to deregister the controller before releasing underlying resources like DMA during driver unbind. Fixes: ccdc7bf92573 ("SPI: omap2_mcspi driver") Cc: stable@vger.kernel.org # 2.6.23 Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-6-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index a3468e47e77d..56b30ff58771 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1592,7 +1592,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) if (status < 0) goto disable_pm; - status = devm_spi_register_controller(&pdev->dev, ctlr); + status = spi_register_controller(ctlr); if (status < 0) goto disable_pm; @@ -1613,11 +1613,17 @@ static void omap2_mcspi_remove(struct platform_device *pdev) struct spi_controller *ctlr = platform_get_drvdata(pdev); struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr); + spi_controller_get(ctlr); + + spi_unregister_controller(ctlr); + omap2_mcspi_release_dma(ctlr); pm_runtime_dont_use_autosuspend(mcspi->dev); pm_runtime_put_sync(mcspi->dev); pm_runtime_disable(&pdev->dev); + + spi_controller_put(ctlr); } /* work with hotplug and coldplug */ From 6b627bfe0c44e064aba464839e430dc1ca2b0bb8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:36 +0200 Subject: [PATCH 090/115] spi: pic32: fix controller deregistration Make sure to deregister the controller before releasing underlying resources like DMA during driver unbind. Fixes: 1bcb9f8ceb67 ("spi: spi-pic32: Add PIC32 SPI master driver") Cc: stable@vger.kernel.org # 4.7 Cc: Purna Chandra Mandal Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-7-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-pic32.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c index 369850d14313..70427e529945 100644 --- a/drivers/spi/spi-pic32.c +++ b/drivers/spi/spi-pic32.c @@ -821,7 +821,7 @@ static int pic32_spi_probe(struct platform_device *pdev) } /* register host */ - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&host->dev, "failed registering spi host\n"); goto err_bailout; @@ -840,11 +840,16 @@ static int pic32_spi_probe(struct platform_device *pdev) static void pic32_spi_remove(struct platform_device *pdev) { - struct pic32_spi *pic32s; + struct pic32_spi *pic32s = platform_get_drvdata(pdev); + + spi_controller_get(pic32s->host); + + spi_unregister_controller(pic32s->host); - pic32s = platform_get_drvdata(pdev); pic32_spi_disable(pic32s); pic32_spi_dma_unprep(pic32s); + + spi_controller_put(pic32s->host); } static const struct of_device_id pic32_spi_of_match[] = { From 420df79d1a618951eb0eb4331df95c9f4f763b8b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:37 +0200 Subject: [PATCH 091/115] spi: pic32-sqi: fix controller deregistration Make sure to deregister the controller before releasing underlying resources like DMA during driver unbind. Fixes: 3270ac230f66 ("spi: pic32-sqi: add SPI driver for PIC32 SQI controller.") Cc: stable@vger.kernel.org # 4.7 Cc: Purna Chandra Mandal Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-8-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-pic32-sqi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-pic32-sqi.c b/drivers/spi/spi-pic32-sqi.c index 051590038895..41662992dbe5 100644 --- a/drivers/spi/spi-pic32-sqi.c +++ b/drivers/spi/spi-pic32-sqi.c @@ -642,7 +642,7 @@ static int pic32_sqi_probe(struct platform_device *pdev) host->prepare_transfer_hardware = pic32_sqi_prepare_hardware; host->unprepare_transfer_hardware = pic32_sqi_unprepare_hardware; - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&host->dev, "failed registering spi host\n"); free_irq(sqi->irq, sqi); @@ -665,9 +665,15 @@ static void pic32_sqi_remove(struct platform_device *pdev) { struct pic32_sqi *sqi = platform_get_drvdata(pdev); + spi_controller_get(sqi->host); + + spi_unregister_controller(sqi->host); + /* release resources */ free_irq(sqi->irq, sqi); ring_desc_ring_free(sqi); + + spi_controller_put(sqi->host); } static const struct of_device_id pic32_sqi_of_ids[] = { From 994b33366be9148240690e3e94bffe17c4d89458 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:38 +0200 Subject: [PATCH 092/115] spi: pl022: fix controller deregistration Make sure to deregister the controller before releasing underlying resources like DMA during driver unbind. Fixes: b43d65f7e818 ("[ARM] 5546/1: ARM PL022 SSP/SPI driver v3") Cc: stable@vger.kernel.org # 2.6.31 Cc: Linus Walleij Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-9-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-pl022.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index bd1d28caa51e..9c0211f94fd0 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -1956,7 +1956,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) /* Register with the SPI framework */ amba_set_drvdata(adev, pl022); - status = devm_spi_register_controller(&adev->dev, host); + status = spi_register_controller(host); if (status != 0) { dev_err_probe(&adev->dev, status, "problem registering spi host\n"); @@ -1997,6 +1997,10 @@ pl022_remove(struct amba_device *adev) if (!pl022) return; + spi_controller_get(pl022->host); + + spi_unregister_controller(pl022->host); + /* * undo pm_runtime_put() in probe. I assume that we're not * accessing the primecell here. @@ -2008,6 +2012,8 @@ pl022_remove(struct amba_device *adev) pl022_dma_remove(pl022); amba_release_regions(adev); + + spi_controller_put(pl022->host); } #ifdef CONFIG_PM_SLEEP From 443e3a0005a4342b218b6dbd4c6387d3c7fed85a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:39 +0200 Subject: [PATCH 093/115] spi: qup: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like clocks during driver unbind. Fixes: 64ff247a978f ("spi: Add Qualcomm QUP SPI controller support") Cc: stable@vger.kernel.org # 3.15 Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-10-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-qup.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index 6cbdcd060e8c..45d9b4cb75e4 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -1193,7 +1193,7 @@ static int spi_qup_probe(struct platform_device *pdev) pm_runtime_set_active(dev); pm_runtime_enable(dev); - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) goto disable_pm; @@ -1320,6 +1320,10 @@ static void spi_qup_remove(struct platform_device *pdev) struct spi_qup *controller = spi_controller_get_devdata(host); int ret; + spi_controller_get(host); + + spi_unregister_controller(host); + ret = pm_runtime_get_sync(&pdev->dev); if (ret >= 0) { @@ -1339,6 +1343,8 @@ static void spi_qup_remove(struct platform_device *pdev) pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + + spi_controller_put(host); } static const struct of_device_id spi_qup_dt_match[] = { From 9944fa6726afb1e6eb7e2212764e7da0c97f2dcc Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:40 +0200 Subject: [PATCH 094/115] spi: rspi: fix controller deregistration Make sure to deregister the controller before releasing underlying resources like DMA during driver unbind. Fixes: 9e03d05eee4c ("spi: rcar: Use devm_spi_register_master()") Cc: stable@vger.kernel.org # 3.14 Cc: Jingoo Han Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-11-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index c739c1998b4c..a8180dece716 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -1171,8 +1171,14 @@ static void rspi_remove(struct platform_device *pdev) { struct rspi_data *rspi = platform_get_drvdata(pdev); + spi_controller_get(rspi->ctlr); + + spi_unregister_controller(rspi->ctlr); + rspi_release_dma(rspi->ctlr); pm_runtime_disable(&pdev->dev); + + spi_controller_put(rspi->ctlr); } static const struct spi_ops rspi_ops = { @@ -1376,9 +1382,9 @@ static int rspi_probe(struct platform_device *pdev) if (ret < 0) dev_warn(&pdev->dev, "DMA not available, using PIO\n"); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); + dev_err(&pdev->dev, "failed to register controller\n"); goto error3; } From c1446b61e472da24d1547525193467b4bea4a7cb Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:41 +0200 Subject: [PATCH 095/115] spi: s3c64xx: fix controller deregistration Make sure to deregister the controller before releasing underlying resources like DMA during driver unbind. Fixes: 91800f0e9005 ("spi/s3c64xx: Use managed registration") Cc: stable@vger.kernel.org # 3.13: 76fbad410c0f Cc: stable@vger.kernel.org # 3.13 Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-12-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index ba85243d6d89..95b61264b679 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1369,7 +1369,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN, sdd->regs + S3C64XX_SPI_INT_EN); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret != 0) { dev_err(&pdev->dev, "cannot register SPI host: %d\n", ret); goto err_pm_put; @@ -1399,6 +1399,8 @@ static void s3c64xx_spi_remove(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); + spi_unregister_controller(host); + writel(0, sdd->regs + S3C64XX_SPI_INT_EN); if (!is_polling(sdd)) { From e63982e6392e45a6ecd68d6c317a081cc8e70143 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:42 +0200 Subject: [PATCH 096/115] spi: sh-hspi: fix controller deregistration Make sure to deregister the controller before releasing underlying resources like clocks during driver unbind. Fixes: 49e599b8595f ("spi: sh-hspi: control spi clock more correctly") Cc: stable@vger.kernel.org # 3.4 Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-13-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-sh-hspi.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c index e03eaca1b1a7..1e3ca718ca73 100644 --- a/drivers/spi/spi-sh-hspi.c +++ b/drivers/spi/spi-sh-hspi.c @@ -257,9 +257,9 @@ static int hspi_probe(struct platform_device *pdev) ctlr->transfer_one_message = hspi_transfer_one_message; ctlr->bits_per_word_mask = SPI_BPW_MASK(8); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); + dev_err(&pdev->dev, "failed to register controller\n"); goto error2; } @@ -279,9 +279,15 @@ static void hspi_remove(struct platform_device *pdev) { struct hspi_priv *hspi = platform_get_drvdata(pdev); + spi_controller_get(hspi->ctlr); + + spi_unregister_controller(hspi->ctlr); + pm_runtime_disable(&pdev->dev); clk_put(hspi->clk); + + spi_controller_put(hspi->ctlr); } static const struct of_device_id hspi_of_match[] = { From 45170f67a08b912ead6ccc387ba06954d1d4e53a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:43 +0200 Subject: [PATCH 097/115] spi: sh-msiof: fix controller deregistration Make sure to deregister the controller before releasing underlying resources like DMA during driver unbind. Fixes: 1bd6363bc0c6 ("spi: sh-msiof: Use core message handling instead of spi-bitbang") Cc: stable@vger.kernel.org # 3.15 Cc: Geert Uytterhoeven Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-14-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-sh-msiof.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 7f3e08810560..f114b6313f4f 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -1289,9 +1289,9 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) if (ret < 0) dev_warn(dev, "DMA not available, using PIO\n"); - ret = devm_spi_register_controller(dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(dev, "devm_spi_register_controller error.\n"); + dev_err(dev, "failed to register controller\n"); goto err2; } @@ -1309,8 +1309,14 @@ static void sh_msiof_spi_remove(struct platform_device *pdev) { struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev); + spi_controller_get(p->ctlr); + + spi_unregister_controller(p->ctlr); + sh_msiof_release_dma(p); pm_runtime_disable(&pdev->dev); + + spi_controller_put(p->ctlr); } static const struct platform_device_id spi_driver_ids[] = { From 0f25236694a2854627c1597465a071e6bb6fe572 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:44 +0200 Subject: [PATCH 098/115] spi: sifive: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like interrupts during driver unbind. Note that clocks were also disabled before the recent commit 140039c23aca ("spi: sifive: Simplify clock handling with devm_clk_get_enabled()"). Fixes: 484a9a68d669 ("spi: sifive: Add driver for the SiFive SPI controller") Cc: stable@vger.kernel.org # 5.1 Cc: Yash Shah Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-15-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-sifive.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c index 54adbc057af6..74a3e32fd2b5 100644 --- a/drivers/spi/spi-sifive.c +++ b/drivers/spi/spi-sifive.c @@ -392,7 +392,7 @@ static int sifive_spi_probe(struct platform_device *pdev) dev_info(&pdev->dev, "mapped; irq=%d, cs=%d\n", irq, host->num_chipselect); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret < 0) { dev_err(&pdev->dev, "spi_register_host failed\n"); goto put_host; @@ -411,8 +411,14 @@ static void sifive_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct sifive_spi *spi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + /* Disable all the interrupts just in case */ sifive_spi_write(spi, SIFIVE_SPI_REG_IE, 0); + + spi_controller_put(host); } static int sifive_spi_suspend(struct device *dev) From ab840cbda4fe6c40e52f6415c47056797c663bb2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:45 +0200 Subject: [PATCH 099/115] spi: slave-mt27xx: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like clocks (by disabling runtime PM) during driver unbind. Fixes: 805be7ddf367 ("spi: mediatek: add spi slave for Mediatek MT2712") Cc: stable@vger.kernel.org # 4.20 Cc: Leilk Liu Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-16-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-slave-mt27xx.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-slave-mt27xx.c b/drivers/spi/spi-slave-mt27xx.c index ce889cb33228..7aedeaa5889d 100644 --- a/drivers/spi/spi-slave-mt27xx.c +++ b/drivers/spi/spi-slave-mt27xx.c @@ -453,7 +453,7 @@ static int mtk_spi_slave_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); clk_disable_unprepare(mdata->spi_clk); if (ret) { dev_err(&pdev->dev, @@ -473,7 +473,15 @@ static int mtk_spi_slave_probe(struct platform_device *pdev) static void mtk_spi_slave_remove(struct platform_device *pdev) { + struct spi_controller *ctlr = platform_get_drvdata(pdev); + + spi_controller_get(ctlr); + + spi_unregister_controller(ctlr); + pm_runtime_disable(&pdev->dev); + + spi_controller_put(ctlr); } #ifdef CONFIG_PM_SLEEP From 123d17dbc5f07059752fa5e616385ca29a8f935a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:46 +0200 Subject: [PATCH 100/115] spi: sprd: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like clocks during driver unbind. Note that the controller is suspended before disabling and releasing resources since commit de082d866cce ("spi: sprd: Add the SPI irq function for the SPI DMA mode") which avoids issues like unclocked accesses but prevents SPI device drivers from doing I/O during deregistration. Fixes: e7d973a31c24 ("spi: sprd: Add SPI driver for Spreadtrum SC9860") Cc: stable@vger.kernel.org # 4.20 Cc: Lanqing Liu Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-17-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-sprd.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-sprd.c b/drivers/spi/spi-sprd.c index 0f9fc320363c..fd3fd0ce122c 100644 --- a/drivers/spi/spi-sprd.c +++ b/drivers/spi/spi-sprd.c @@ -977,7 +977,7 @@ static int sprd_spi_probe(struct platform_device *pdev) goto err_rpm_put; } - ret = devm_spi_register_controller(&pdev->dev, sctlr); + ret = spi_register_controller(sctlr); if (ret) goto err_rpm_put; @@ -1008,7 +1008,9 @@ static void sprd_spi_remove(struct platform_device *pdev) if (ret < 0) dev_err(ss->dev, "failed to resume SPI controller\n"); - spi_controller_suspend(sctlr); + spi_controller_get(sctlr); + + spi_unregister_controller(sctlr); if (ret >= 0) { if (ss->dma.enable) @@ -1017,6 +1019,8 @@ static void sprd_spi_remove(struct platform_device *pdev) } pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + + spi_controller_put(sctlr); } static int __maybe_unused sprd_spi_runtime_suspend(struct device *dev) From 19857374010d06ca6a2f7c2c53464122eb804df0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:47 +0200 Subject: [PATCH 101/115] spi: st-ssc4: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like clocks during driver unbind. Fixes: 9e862375c542 ("spi: Add new driver for STMicroelectronics' SPI Controller") Cc: stable@vger.kernel.org # 4.0 Cc: Lee Jones Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-18-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-st-ssc4.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-st-ssc4.c b/drivers/spi/spi-st-ssc4.c index b173ef70d77e..9c8099fe6e19 100644 --- a/drivers/spi/spi-st-ssc4.c +++ b/drivers/spi/spi-st-ssc4.c @@ -349,7 +349,7 @@ static int spi_st_probe(struct platform_device *pdev) platform_set_drvdata(pdev, host); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&pdev->dev, "Failed to register host\n"); goto rpm_disable; @@ -371,10 +371,16 @@ static void spi_st_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct spi_st *spi_st = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_disable(&pdev->dev); clk_disable_unprepare(spi_st->clk); + spi_controller_put(host); + pinctrl_pm_select_sleep_state(&pdev->dev); } From 42108a2f03e0fdeabe9d02d085bdb058baa1189f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:48 +0200 Subject: [PATCH 102/115] spi: sun4i: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like clocks during driver unbind. Fixes: b5f6517948cc ("spi: sunxi: Add Allwinner A10 SPI controller driver") Cc: stable@vger.kernel.org # 3.15 Cc: Maxime Ripard Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-19-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-sun4i.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c index bfdf419a583c..b7fbb5270edb 100644 --- a/drivers/spi/spi-sun4i.c +++ b/drivers/spi/spi-sun4i.c @@ -504,7 +504,7 @@ static int sun4i_spi_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_idle(&pdev->dev); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&pdev->dev, "cannot register SPI host\n"); goto err_pm_disable; @@ -522,7 +522,15 @@ static int sun4i_spi_probe(struct platform_device *pdev) static void sun4i_spi_remove(struct platform_device *pdev) { + struct spi_controller *host = platform_get_drvdata(pdev); + + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_force_suspend(&pdev->dev); + + spi_controller_put(host); } static const struct of_device_id sun4i_spi_match[] = { From d874a1c33aee0d88fb4ba2f8aeadaa9f1965209a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:49 +0200 Subject: [PATCH 103/115] spi: sun6i: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like clocks during driver unbind. Fixes: 3558fe900e8a ("spi: sunxi: Add Allwinner A31 SPI controller driver") Cc: stable@vger.kernel.org # 3.15 Cc: Maxime Ripard Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-20-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-sun6i.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c index 240e46f84f7b..5ac73d324d06 100644 --- a/drivers/spi/spi-sun6i.c +++ b/drivers/spi/spi-sun6i.c @@ -742,7 +742,7 @@ static int sun6i_spi_probe(struct platform_device *pdev) pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&pdev->dev, "cannot register SPI host\n"); goto err_pm_disable; @@ -768,12 +768,18 @@ static void sun6i_spi_remove(struct platform_device *pdev) { struct spi_controller *host = platform_get_drvdata(pdev); + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_force_suspend(&pdev->dev); if (host->dma_tx) dma_release_channel(host->dma_tx); if (host->dma_rx) dma_release_channel(host->dma_rx); + + spi_controller_put(host); } static const struct sun6i_spi_cfg sun6i_a31_spi_cfg = { From 75d849c3452e9611de031db45b3149ba9a99035f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:50 +0200 Subject: [PATCH 104/115] spi: syncuacer: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like clocks during driver unbind. Fixes: b0823ee35cf9 ("spi: Add spi driver for Socionext SynQuacer platform") Cc: stable@vger.kernel.org # 5.3 Cc: Masahisa Kojima Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-21-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-synquacer.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-synquacer.c b/drivers/spi/spi-synquacer.c index d0a875249910..290c439897c4 100644 --- a/drivers/spi/spi-synquacer.c +++ b/drivers/spi/spi-synquacer.c @@ -716,7 +716,7 @@ static int synquacer_spi_probe(struct platform_device *pdev) pm_runtime_set_active(sspi->dev); pm_runtime_enable(sspi->dev); - ret = devm_spi_register_controller(sspi->dev, host); + ret = spi_register_controller(host); if (ret) goto disable_pm; @@ -737,9 +737,15 @@ static void synquacer_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct synquacer_spi *sspi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_disable(sspi->dev); clk_disable_unprepare(sspi->clk); + + spi_controller_put(host); } static int __maybe_unused synquacer_spi_suspend(struct device *dev) From 9c9c27ff2058142d8f800de3186d6864184958de Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:51 +0200 Subject: [PATCH 105/115] spi: tegra114: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like clocks during driver unbind. Fixes: 5c8096439600 ("spi: tegra114: use devm_spi_register_master()") Cc: stable@vger.kernel.org # 3.13 Cc: Jingoo Han Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-22-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 848cb6836bd5..b8b0ebe0fe93 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -1415,7 +1415,7 @@ static int tegra_spi_probe(struct platform_device *pdev) goto exit_pm_disable; } - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret < 0) { dev_err(&pdev->dev, "can not register to host err %d\n", ret); goto exit_free_irq; @@ -1441,6 +1441,10 @@ static void tegra_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct tegra_spi_data *tspi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + free_irq(tspi->irq, tspi); if (tspi->tx_dma_chan) @@ -1452,6 +1456,8 @@ static void tegra_spi_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) tegra_spi_runtime_suspend(&pdev->dev); + + spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP From ad7310e983327f939dd6c4e801eab13238992572 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:52 +0200 Subject: [PATCH 106/115] spi: tegra20-sflash: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like clocks during driver unbind. Fixes: f12f7318c44a ("spi: tegra20-sflash: use devm_spi_register_master()") Cc: stable@vger.kernel.org # 3.13 Cc: Jingoo Han Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-23-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-tegra20-sflash.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index d9d536d7f7b6..9256729f2d49 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -505,7 +505,7 @@ static int tegra_sflash_probe(struct platform_device *pdev) tegra_sflash_writel(tsd, tsd->def_command_reg, SPI_COMMAND); pm_runtime_put(&pdev->dev); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret < 0) { dev_err(&pdev->dev, "can not register to host err %d\n", ret); goto exit_pm_disable; @@ -528,11 +528,17 @@ static void tegra_sflash_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct tegra_sflash_data *tsd = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + free_irq(tsd->irq, tsd); pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) tegra_sflash_runtime_suspend(&pdev->dev); + + spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP From 0c18a1bacbb1d8b8aa34d3d004a2cb8226c8b1ea Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:53 +0200 Subject: [PATCH 107/115] spi: ti-qspi: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like clocks during driver unbind. Note that the controller is suspended before disabling and releasing resources since commit 3ac066e2227c ("spi: spi-ti-qspi: Suspend the queue before removing the device") which avoids issues like unclocked accesses but prevents SPI device drivers from doing I/O during deregistration. Fixes: 3b3a80019ff1 ("spi: ti-qspi: one only one interrupt handler") Cc: stable@vger.kernel.org # 3.13 Cc: Sebastian Andrzej Siewior Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-24-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-ti-qspi.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index d1d880a8ed7d..1fbd710d616f 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -888,7 +888,7 @@ static int ti_qspi_probe(struct platform_device *pdev) qspi->mmap_enabled = false; qspi->current_cs = -1; - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (!ret) return 0; @@ -903,19 +903,17 @@ static int ti_qspi_probe(struct platform_device *pdev) static void ti_qspi_remove(struct platform_device *pdev) { struct ti_qspi *qspi = platform_get_drvdata(pdev); - int rc; - rc = spi_controller_suspend(qspi->host); - if (rc) { - dev_alert(&pdev->dev, "spi_controller_suspend() failed (%pe)\n", - ERR_PTR(rc)); - return; - } + spi_controller_get(qspi->host); + + spi_unregister_controller(qspi->host); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); ti_qspi_dma_cleanup(qspi); + + spi_controller_put(qspi->host); } static const struct dev_pm_ops ti_qspi_pm_ops = { From 0245435f777264ac45945ed2f325dd095a41d1af Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:54 +0200 Subject: [PATCH 108/115] spi: uniphier: fix controller deregistration Make sure to deregister the controller before releasing underlying resources like DMA during driver unbind. Note that clocks were also disabled before the recent commit fdca270f8f87 ("spi: uniphier: Simplify clock handling with devm_clk_get_enabled()"). Fixes: 5ba155a4d4cc ("spi: add SPI controller driver for UniPhier SoC") Cc: stable@vger.kernel.org # 4.19 Cc: Keiji Hayashibara Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-25-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-uniphier.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-uniphier.c b/drivers/spi/spi-uniphier.c index 1b815ee2ed1b..eac6c3e8908b 100644 --- a/drivers/spi/spi-uniphier.c +++ b/drivers/spi/spi-uniphier.c @@ -746,7 +746,7 @@ static int uniphier_spi_probe(struct platform_device *pdev) host->max_dma_len = min(dma_tx_burst, dma_rx_burst); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) goto out_release_dma; @@ -771,10 +771,16 @@ static void uniphier_spi_remove(struct platform_device *pdev) { struct spi_controller *host = platform_get_drvdata(pdev); + spi_controller_get(host); + + spi_unregister_controller(host); + if (host->dma_tx) dma_release_channel(host->dma_tx); if (host->dma_rx) dma_release_channel(host->dma_rx); + + spi_controller_put(host); } static const struct of_device_id uniphier_spi_match[] = { From 6895fc4faafc9082e15e4e624b23dd5f0c98feb5 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:55 +0200 Subject: [PATCH 109/115] spi: zynqmp-gqspi: fix controller deregistration Make sure to deregister the controller before disabling underlying resources like clocks during driver unbind. Fixes: dfe11a11d523 ("spi: Add support for Zynq Ultrascale+ MPSoC GQSPI controller") Cc: stable@vger.kernel.org # 4.2: 64640f6c972e Cc: stable@vger.kernel.org # 4.2 Cc: Ranjit Waghmode Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-26-johan@kernel.org 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 502fd5eccc83..f9a1427dabad 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -1324,7 +1324,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) ctlr->dev.of_node = np; ctlr->auto_runtime_pm = true; - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret) { dev_err(&pdev->dev, "spi_register_controller failed\n"); goto clk_dis_all; @@ -1362,6 +1362,8 @@ static void zynqmp_qspi_remove(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); + spi_unregister_controller(xqspi->ctlr); + zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, 0x0); pm_runtime_disable(&pdev->dev); From c9c012706c9fa8ca6d129a9161caf92ab625a3fd Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 10:17:56 +0200 Subject: [PATCH 110/115] spi: zynq-qspi: fix controller deregistration Make sure to deregister the controller before disabling it during driver unbind. Note that clocks were also disabled before the recent commit 1f8fd9490e31 ("spi: zynq-qspi: Simplify clock handling with devm_clk_get_enabled()"). Fixes: 67dca5e580f1 ("spi: spi-mem: Add support for Zynq QSPI controller") Cc: stable@vger.kernel.org # 5.2: 8eb2fd00f65a Cc: stable@vger.kernel.org # 5.2 Cc: Naga Sureshkumar Relli Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410081757.503099-27-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-zynq-qspi.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c index af252500195c..406fd9d5337e 100644 --- a/drivers/spi/spi-zynq-qspi.c +++ b/drivers/spi/spi-zynq-qspi.c @@ -643,7 +643,7 @@ static int zynq_qspi_probe(struct platform_device *pdev) xqspi = spi_controller_get_devdata(ctlr); xqspi->dev = dev; - platform_set_drvdata(pdev, xqspi); + platform_set_drvdata(pdev, ctlr); xqspi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(xqspi->regs)) { ret = PTR_ERR(xqspi->regs); @@ -702,9 +702,9 @@ static int zynq_qspi_probe(struct platform_device *pdev) /* QSPI controller initializations */ zynq_qspi_init_hw(xqspi, ctlr->num_chipselect); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret) { - dev_err(&pdev->dev, "devm_spi_register_controller failed\n"); + dev_err(&pdev->dev, "failed to register controller\n"); goto remove_ctlr; } @@ -728,9 +728,16 @@ static int zynq_qspi_probe(struct platform_device *pdev) */ static void zynq_qspi_remove(struct platform_device *pdev) { - struct zynq_qspi *xqspi = platform_get_drvdata(pdev); + struct spi_controller *ctlr = platform_get_drvdata(pdev); + struct zynq_qspi *xqspi = spi_controller_get_devdata(ctlr); + + spi_controller_get(ctlr); + + spi_unregister_controller(ctlr); zynq_qspi_write(xqspi, ZYNQ_QSPI_ENABLE_OFFSET, 0); + + spi_controller_put(ctlr); } static const struct of_device_id zynq_qspi_of_match[] = { From 45daacbead8a009844bd5dba6cfa731332184d17 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Apr 2026 11:49:25 +0200 Subject: [PATCH 111/115] spi: s3c64xx: fix NULL-deref on driver unbind A change moving DMA channel allocation from probe() back to s3c64xx_spi_prepare_transfer() failed to remove the corresponding deallocation from remove(). Drop the bogus DMA channel release from remove() to avoid triggering a NULL-pointer dereference on driver unbind. This issue was flagged by Sashiko when reviewing a controller deregistration fix. Fixes: f52b03c70744 ("spi: s3c64xx: requests spi-dma channel only during data transfer") Cc: stable@vger.kernel.org # 6.0 Cc: Adithya K V Link: https://sashiko.dev/#/patchset/20260410081757.503099-1-johan%40kernel.org Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260410094925.518343-1-johan@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 95b61264b679..37176e557099 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1403,11 +1403,6 @@ static void s3c64xx_spi_remove(struct platform_device *pdev) writel(0, sdd->regs + S3C64XX_SPI_INT_EN); - if (!is_polling(sdd)) { - dma_release_channel(sdd->rx_dma.ch); - dma_release_channel(sdd->tx_dma.ch); - } - pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); From ab00febad191d7a4400aa1c3468279fb508258d4 Mon Sep 17 00:00:00 2001 From: Pei Xiao Date: Tue, 7 Apr 2026 15:26:59 +0800 Subject: [PATCH 112/115] spi: mtk-snfi: unregister ECC engine on probe failure and remove() callback mtk_snand_probe() registers the on-host NAND ECC engine, but teardown was missing from both probe unwind and remove-time cleanup. Add a devm cleanup action after successful registration so nand_ecc_unregister_on_host_hw_engine() runs automatically on probe failures and during device removal. Fixes: 764f1b748164 ("spi: add driver for MTK SPI NAND Flash Interface") Signed-off-by: Pei Xiao Link: https://patch.msgid.link/20263f885f1a9c9d559f95275298cd6de4b11ed5.1775546401.git.xiaopei01@kylinos.cn Signed-off-by: Mark Brown --- drivers/spi/spi-mtk-snfi.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/spi/spi-mtk-snfi.c b/drivers/spi/spi-mtk-snfi.c index 437edbd658aa..73fa84475f0e 100644 --- a/drivers/spi/spi-mtk-snfi.c +++ b/drivers/spi/spi-mtk-snfi.c @@ -1303,6 +1303,13 @@ static const struct spi_controller_mem_caps mtk_snand_mem_caps = { .ecc = true, }; +static void mtk_unregister_ecc_engine(void *data) +{ + struct nand_ecc_engine *eng = data; + + nand_ecc_unregister_on_host_hw_engine(eng); +} + static irqreturn_t mtk_snand_irq(int irq, void *id) { struct mtk_snand *snf = id; @@ -1443,6 +1450,13 @@ static int mtk_snand_probe(struct platform_device *pdev) goto release_ecc; } + ret = devm_add_action_or_reset(&pdev->dev, mtk_unregister_ecc_engine, + &ms->ecc_eng); + if (ret) { + dev_err_probe(&pdev->dev, ret, "failed to add ECC unregister action\n"); + goto release_ecc; + } + ctlr->num_chipselect = 1; ctlr->mem_ops = &mtk_snand_mem_ops; ctlr->mem_caps = &mtk_snand_mem_caps; From 5e75c1d4d386fb7d64e2b19355e4d38dd4fd8845 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 10 Apr 2026 19:41:01 +0200 Subject: [PATCH 113/115] spi: cadence-qspi: Revert the filtering of certain opcodes in ODTR I got mislead while analyzing the driver by the fact that the second opcode byte was in all cases smashed: if (op->cmd.dtr) opcode = op->cmd.opcode >> 8; else opcode = op->cmd.opcode; While at a first glance this doesn't let a chance to the second byte to be shifted out on the bus, this is actually the second step of an initialization, where the byte being apparently "ignored" in DTR mode has already been written in a dedicated "extended opcode" register. As such, the comment and the extra check that I proposed were entirely wrong, remove them. Fixes: bee085476d27 ("spi: cadence-qspi: Make sure we filter out unsupported ops") Signed-off-by: Miquel Raynal Link: https://patch.msgid.link/20260410-winbond-6-19-rc1-oddr-v1-1-2ac4827a3868@bootlin.com Signed-off-by: Mark Brown --- drivers/spi/spi-cadence-quadspi.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index 2ead419e896e..b6f7f95e8bd3 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -1544,10 +1544,6 @@ static bool cqspi_supports_mem_op(struct spi_mem *mem, if (op->data.nbytes && op->data.buswidth != 8) return false; - /* A single opcode is supported, it will be repeated */ - if ((op->cmd.opcode >> 8) != (op->cmd.opcode & 0xFF)) - return false; - if (cqspi->is_rzn1) return false; } else if (!all_false) { From f79ee9e4b23244e77b28d176ce99a2d84d813ac5 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 10 Apr 2026 19:41:02 +0200 Subject: [PATCH 114/115] spi: spi-mem: Add a packed command operation Instead of repeating the command opcode twice, some flash devices try to pack command and address bits. In this case, the second opcode byte being sent (LSB) is free to be used. The input data must be ANDed to only provide the relevant bits. Signed-off-by: Miquel Raynal Link: https://patch.msgid.link/20260410-winbond-6-19-rc1-oddr-v1-2-2ac4827a3868@bootlin.com Signed-off-by: Mark Brown --- include/linux/spi/spi-mem.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h index 37f709784350..c8e207522223 100644 --- a/include/linux/spi/spi-mem.h +++ b/include/linux/spi/spi-mem.h @@ -28,6 +28,14 @@ .dtr = true, \ } +#define SPI_MEM_DTR_OP_PACKED_CMD(__opcode, __addr, __buswidth) \ + { \ + .nbytes = 2, \ + .opcode = __opcode << 8 | __addr, \ + .buswidth = __buswidth, \ + .dtr = true, \ + } + #define SPI_MEM_OP_ADDR(__nbytes, __val, __buswidth) \ { \ .nbytes = __nbytes, \ From c4c3fc872d2a05bf10372233c98e81344e685cdf Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Sat, 11 Apr 2026 19:49:38 +0800 Subject: [PATCH 115/115] spi: sn-f-ospi: fix incorrect return code for invalid num-cs Returning -ENOMEM for an invalid num-cs value is semantically wrong. Use -EINVAL instead. Signed-off-by: Felix Gu Link: https://patch.msgid.link/20260411-ispi-v1-1-af384e81c4c8@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-sn-f-ospi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-sn-f-ospi.c b/drivers/spi/spi-sn-f-ospi.c index 3c61c799723b..b459d51cb3a8 100644 --- a/drivers/spi/spi-sn-f-ospi.c +++ b/drivers/spi/spi-sn-f-ospi.c @@ -625,7 +625,7 @@ static int f_ospi_probe(struct platform_device *pdev) of_property_read_u32(dev->of_node, "num-cs", &num_cs); if (num_cs > OSPI_NUM_CS) { dev_err(dev, "num-cs too large: %d\n", num_cs); - return -ENOMEM; + return -EINVAL; } ctlr->num_chipselect = num_cs;