[PATCH] spi: rspi: Fix DMA mode when the DMA controller is built as a module
From: Ovidiu Panait
Date: Mon Sep 21 2026 - 16:23:43 EST
On the Renesas RZ/G2L platform, the RSPI driver falls back to PIO mode
instead of using DMA when the DMA controller driver is built as a module
(CONFIG_RZ_DMAC=m):
renesas_spi 1004b000.spi: dma_request_slave_channel_compat failed
renesas_spi 1004b000.spi: DMA not available, using PIO
The driver requests DMA channels through dma_request_slave_channel_compat()
which returns either a valid pointer or NULL and cannot handle
-EPROBE_DEFER. If the DMA controller has not probed yet, the driver falls
back to PIO directly.
Fix this by replacing the dma_request_slave_channel_compat() call with a
regular dma_request_chan() call. dma_request_slave_channel_compat() is
always passed a NULL fn_param in all code paths, so it actually behaves
like a plain dma_request_chan() call.
Fixes: e825b8dd2b36 ("spi: rspi: Add DT support to DMA setup")
Signed-off-by: Ovidiu Panait <ovidiu.panait.rb@xxxxxxxxxxx>
---
drivers/spi/spi-rspi.c | 49 ++++++++++++++++--------------------------
1 file changed, 19 insertions(+), 30 deletions(-)
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 38df676774ee..c61edd1c1353 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -22,7 +22,6 @@
#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
-#include <linux/sh_dma.h>
#include <linux/spi/spi.h>
#include <linux/spinlock.h>
@@ -1091,24 +1090,15 @@ static irqreturn_t rspi_irq_tx(int irq, void *_sr)
static struct dma_chan *rspi_request_dma_chan(struct device *dev,
enum dma_transfer_direction dir,
- unsigned int id,
dma_addr_t port_addr)
{
- dma_cap_mask_t mask;
struct dma_chan *chan;
struct dma_slave_config cfg;
int ret;
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
-
- chan = dma_request_slave_channel_compat(mask, shdma_chan_filter,
- (void *)(unsigned long)id, dev,
- dir == DMA_MEM_TO_DEV ? "tx" : "rx");
- if (!chan) {
- dev_warn(dev, "dma_request_slave_channel_compat failed\n");
- return NULL;
- }
+ chan = dma_request_chan(dev, dir == DMA_MEM_TO_DEV ? "tx" : "rx");
+ if (IS_ERR(chan))
+ return chan;
memset(&cfg, 0, sizeof(cfg));
cfg.dst_addr = port_addr + RSPI_SPDR;
@@ -1121,7 +1111,7 @@ static struct dma_chan *rspi_request_dma_chan(struct device *dev,
if (ret) {
dev_warn(dev, "dmaengine_slave_config failed %d\n", ret);
dma_release_channel(chan);
- return NULL;
+ return ERR_PTR(ret);
}
return chan;
@@ -1130,29 +1120,23 @@ static struct dma_chan *rspi_request_dma_chan(struct device *dev,
static int rspi_request_dma(struct device *dev, struct spi_controller *ctlr,
const struct resource *res)
{
- unsigned int dma_tx_id, dma_rx_id;
+ struct dma_chan *chan;
- if (dev->of_node) {
- /* In the OF case we will get the slave IDs from the DT */
- dma_tx_id = 0;
- dma_rx_id = 0;
- } else {
- /* The driver assumes no error. */
+ if (!dev->of_node)
return 0;
- }
- ctlr->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV, dma_tx_id,
- res->start);
- if (!ctlr->dma_tx)
- return -ENODEV;
+ chan = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV, res->start);
+ if (IS_ERR(chan))
+ return PTR_ERR(chan);
+ ctlr->dma_tx = chan;
- ctlr->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM, dma_rx_id,
- res->start);
- if (!ctlr->dma_rx) {
+ chan = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM, res->start);
+ if (IS_ERR(chan)) {
dma_release_channel(ctlr->dma_tx);
ctlr->dma_tx = NULL;
- return -ENODEV;
+ return PTR_ERR(chan);
}
+ ctlr->dma_rx = chan;
ctlr->can_dma = rspi_can_dma;
dev_info(dev, "DMA available");
@@ -1355,6 +1339,11 @@ static int rspi_probe(struct platform_device *pdev)
}
ret = rspi_request_dma(&pdev->dev, ctlr, res);
+ if (ret == -EPROBE_DEFER) {
+ dev_err_probe(&pdev->dev, ret,
+ "failed to request DMA channels\n");
+ goto error2;
+ }
if (ret < 0)
dev_warn(&pdev->dev, "DMA not available, using PIO\n");
--
2.34.1