[PATCH v3 2/5] dmaengine: mmp_pdma: support variable extended DRCMR base

Troy Mitchell
2026-04-24T08:22:15Z

From: Guodong Xu <guodong@riscstar.com>

DRCMR base address for extended DMA request numbers (which means bigger
or equal to 64) varies in different PMDA hardware implementation.

One such different PDMA implementation is found in SpacemiT's K3. In
this patch is for preparation the adding of K3 PDMA support.

Signed-off-by: Guodong Xu <guodong@riscstar.com>
Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
---
drivers/dma/mmp_pdma.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
index d12e729ee12c..6112369006ee 100644
--- a/drivers/dma/mmp_pdma.c
+++ b/drivers/dma/mmp_pdma.c
@@ -51,7 +51,9 @@
#define DCSR_CMPST BIT(10) /* The Descriptor Compare Status */
#define DCSR_EORINTR BIT(9) /* The end of Receive */

-#define DRCMR(n) ((((n) < 64) ? 0x0100 : 0x1100) + (((n) & 0x3f) << 2))
+#define DRCMR_BASE 0x0100
+#define DRCMR_EXT_BASE_DEFAULT 0x1100
+#define DRCMR_REQ_LIMIT 64
#define DRCMR_MAPVLD BIT(7) /* Map Valid (read / write) */
#define DRCMR_CHLNUM 0x1f /* mask for Channel Number (read / write) */

@@ -154,6 +156,7 @@ struct mmp_pdma_phy {
* @run_bits: Control bits in DCSR register for channel start/stop
* @dma_width: DMA addressing width in bits (32 or 64). Determines the
* DMA mask capability of the controller hardware.
+ * @drcmr_ext_base: Base DRCMR address for extended requests
*/
struct mmp_pdma_ops {
/* Hardware Register Operations */
@@ -174,6 +177,7 @@ struct mmp_pdma_ops {
/* Controller Configuration */
u32 run_bits;
u32 dma_width;
+ u32 drcmr_ext_base;
};

struct mmp_pdma_device {
@@ -195,6 +199,13 @@ struct mmp_pdma_device {
#define to_mmp_pdma_dev(dmadev) \
container_of(dmadev, struct mmp_pdma_device, device)

+static u32 mmp_pdma_get_drcmr(struct mmp_pdma_device *pdev, u32 drcmr)
+{
+ if (drcmr < DRCMR_REQ_LIMIT)
+ return DRCMR_BASE + (drcmr << 2);
+ return pdev->ops->drcmr_ext_base + ((drcmr - DRCMR_REQ_LIMIT) << 2);
+}
+
/* For 32-bit PDMA */
static void write_next_addr_32(struct mmp_pdma_phy *phy, dma_addr_t addr)
{
@@ -301,7 +312,7 @@ static void enable_chan(struct mmp_pdma_phy *phy)

pdev = to_mmp_pdma_dev(phy->vchan->chan.device);

- reg = DRCMR(phy->vchan->drcmr);
+ reg = mmp_pdma_get_drcmr(pdev, phy->vchan->drcmr);
writel(DRCMR_MAPVLD | phy->idx, phy->base + reg);

dalgn = readl(phy->base + DALGN);
@@ -437,7 +448,7 @@ static void mmp_pdma_free_phy(struct mmp_pdma_chan *pchan)
return;

/* clear the channel mapping in DRCMR */
- reg = DRCMR(pchan->drcmr);
+ reg = mmp_pdma_get_drcmr(pdev, pchan->drcmr);
writel(0, pchan->phy->base + reg);

spin_lock_irqsave(&pdev->phy_lock, flags);
@@ -1179,6 +1190,7 @@ static const struct mmp_pdma_ops marvell_pdma_v1_ops = {
.get_desc_dst_addr = get_desc_dst_addr_32,
.run_bits = (DCSR_RUN),
.dma_width = 32,
+ .drcmr_ext_base = DRCMR_EXT_BASE_DEFAULT,
};

static const struct mmp_pdma_ops spacemit_k1_pdma_ops = {
@@ -1192,6 +1204,7 @@ static const struct mmp_pdma_ops spacemit_k1_pdma_ops = {
.get_desc_dst_addr = get_desc_dst_addr_64,
.run_bits = (DCSR_RUN | DCSR_LPAEEN),
.dma_width = 64,
+ .drcmr_ext_base = DRCMR_EXT_BASE_DEFAULT,
};

static const struct of_device_id mmp_pdma_dt_ids[] = {

--
2.53.0