[PATCH v2 4/5] dmaengine: arm-dma350: Honour dma-channel-mask

From: Jelly Jia

Date: Wed Nov 04 2026 - 07:54:54 EST


DMA-350 channels may be reserved for firmware or another processor.
Read the optional dma-channel-mask property and register only the channels
whose bits are set. If the property is absent, preserve the existing
behaviour and expose every hardware channel.

Skip masked channels before accessing their channel registers or
initializing their interrupts and virt-dma state. This avoids clearing
or configuring channels reserved for firmware or another processor.

Signed-off-by: Jelly Jia <Jelly.Jia@xxxxxxxxxxx>
---
drivers/dma/arm-dma350.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/arm-dma350.c b/drivers/dma/arm-dma350.c
index 2f22f8a0ab47..b24e569a1dd8 100644
--- a/drivers/dma/arm-dma350.c
+++ b/drivers/dma/arm-dma350.c
@@ -1253,9 +1253,10 @@ static int d350_probe(struct platform_device *pdev)
struct clk *clk;
struct d350 *dmac;
void __iomem *base;
+ u32 chan_mask = U32_MAX;
u32 reg;
int ret, nchan, dw, aw, r, p;
- bool coherent, memset;
+ bool coherent, has_chan_mask, memset;

clk = devm_clk_get_optional_enabled(dev, NULL);
if (IS_ERR(clk))
@@ -1328,6 +1329,19 @@ static int d350_probe(struct platform_device *pdev)
dmac->dma.device_caps = d350_caps;
INIT_LIST_HEAD(&dmac->dma.channels);

+ /*
+ * dma-channel-mask is optional. Firmware-reserved channels stay
+ * clear; if the property is absent, Linux may use every channel.
+ */
+ has_chan_mask = device_property_present(dev, "dma-channel-mask");
+ if (has_chan_mask) {
+ ret = device_property_read_u32(dev, "dma-channel-mask",
+ &chan_mask);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to read dma-channel-mask\n");
+ }
+
reg = readl_relaxed(base + DMANSECCTRL + NSEC_CTRL);
writel_relaxed(reg | INTREN_ANYCHINTR_EN,
base + DMANSECCTRL + NSEC_CTRL);
@@ -1337,6 +1351,10 @@ static int d350_probe(struct platform_device *pdev)
for (int i = 0; i < nchan; i++) {
struct d350_chan *dch = &dmac->channels[i];

+ if (has_chan_mask &&
+ (i >= 32 || !(chan_mask & BIT(i))))
+ continue;
+
dch->base = base + DMACH(i);
writel_relaxed(CH_CMD_CLEAR, dch->base + CH_CMD);

--
2.54.0