[PATCH 10/22] ASoC: rsnd: Add DMA support infrastructure for RZ/G3E

John Madieu posted 22 patches 2 weeks, 3 days ago
There is a newer version of this series
[PATCH 10/22] ASoC: rsnd: Add DMA support infrastructure for RZ/G3E
Posted by John Madieu 2 weeks, 3 days ago
RZ/G3E has different DMA register base addresses and offset calculations
compared to R-Car platforms, and requires additional audmac-pp clock and
reset lines for Audio DMAC operation.

Add RZ/G3E-specific DMA address macros and audmac-pp clock/reset support
using optional APIs to remain transparent to other platforms.

Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
---
 sound/soc/renesas/rcar/core.c |   2 +-
 sound/soc/renesas/rcar/dma.c  | 171 +++++++++++++++++++++++++++-------
 sound/soc/renesas/rcar/rsnd.h |  12 +++
 3 files changed, 152 insertions(+), 33 deletions(-)

diff --git a/sound/soc/renesas/rcar/core.c b/sound/soc/renesas/rcar/core.c
index 86b2e9d06f9b..2f9c32c647a6 100644
--- a/sound/soc/renesas/rcar/core.c
+++ b/sound/soc/renesas/rcar/core.c
@@ -615,7 +615,7 @@ int rsnd_dai_connect(struct rsnd_mod *mod,
 	return 0;
 }
 
-static void rsnd_dai_disconnect(struct rsnd_mod *mod,
+void rsnd_dai_disconnect(struct rsnd_mod *mod,
 				struct rsnd_dai_stream *io,
 				enum rsnd_mod_type type)
 {
diff --git a/sound/soc/renesas/rcar/dma.c b/sound/soc/renesas/rcar/dma.c
index 68c859897e68..d3123ae3b402 100644
--- a/sound/soc/renesas/rcar/dma.c
+++ b/sound/soc/renesas/rcar/dma.c
@@ -496,24 +496,71 @@ static struct rsnd_mod_ops rsnd_dmapp_ops = {
  *	SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000
  *	SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000
  *	CMD : 0xec500000 /            / 0xec008000                0xec308000
+ *
+ * 	ex) G3E case
+ *	      mod        / DMAC in    / DMAC out   / DMAC PP in / DMAC pp out
+ *	SSI : 0x13C31000 / 0x13C40000 / 0x13C40000
+ *	SSIU: 0x13C31000 / 0x13C40000 / 0x13C40000 / 0xEC400000 / 0xEC400000
+ *	SCU : 0x13C00000 / 0x13C10000 / 0x13C14000 / 0xEC300000 / 0xEC304000
+ *	CMD : 0x13C00000 /            / 0x13C18000                0xEC308000
  */
-#define RDMA_SSI_I_N(addr, i)	(addr ##_reg - 0x00300000 + (0x40 * i) + 0x8)
-#define RDMA_SSI_O_N(addr, i)	(addr ##_reg - 0x00300000 + (0x40 * i) + 0xc)
 
-#define RDMA_SSIU_I_N(addr, i, j) (addr ##_reg - 0x00441000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
-#define RDMA_SSIU_O_N(addr, i, j) RDMA_SSIU_I_N(addr, i, j)
+/* RZ/G3E DMA address macros */
+#define RDMA_SSI_I_N_G3E(addr, i)	(addr ##_reg + 0x0000F000 + (0x1000 * i))
+#define RDMA_SSI_O_N_G3E(addr, i)	(addr ##_reg + 0x0000F000 + (0x1000 * i))
+
+#define RDMA_SSIU_I_N_G3E(addr, i, j) (addr ##_reg + 0x0000F000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
+#define RDMA_SSIU_O_N_G3E(addr, i, j) RDMA_SSIU_I_N_G3E(addr, i, j)
+
+#define RDMA_SSIU_I_P_G3E(addr, i, j) (addr ##_reg + 0xD87CF000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
+#define RDMA_SSIU_O_P_G3E(addr, i, j) RDMA_SSIU_I_P_G3E(addr, i, j)
+
+#define RDMA_SRC_I_N_G3E(addr, i)	(addr ##_reg + 0x00010000 + (0x400 * i))
+#define RDMA_SRC_O_N_G3E(addr, i)	(addr ##_reg + 0x00014000 + (0x400 * i))
+
+#define RDMA_SRC_I_P_G3E(addr, i)	(addr ##_reg + 0xD8700000 + (0x400 * i))
+#define RDMA_SRC_O_P_G3E(addr, i)	(addr ##_reg + 0xD8704000 + (0x400 * i))
+
+#define RDMA_CMD_O_N_G3E(addr, i)	(addr ##_reg + 0x00018000 + (0x400 * i))
+#define RDMA_CMD_O_P_G3E(addr, i)	(addr ##_reg + 0xD8708000 + (0x400 * i))
+
+/* R-Car DMA address macros */
+#define RDMA_SSI_I_N_RCAR(addr, i)	(addr ##_reg - 0x00300000 + (0x40 * i) + 0x8)
+#define RDMA_SSI_O_N_RCAR(addr, i)	(addr ##_reg - 0x00300000 + (0x40 * i) + 0xc)
 
-#define RDMA_SSIU_I_P(addr, i, j) (addr ##_reg - 0x00141000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
-#define RDMA_SSIU_O_P(addr, i, j) RDMA_SSIU_I_P(addr, i, j)
+#define RDMA_SSIU_I_N_RCAR(addr, i, j) (addr ##_reg - 0x00441000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
+#define RDMA_SSIU_O_N_RCAR(addr, i, j) RDMA_SSIU_I_N_RCAR(addr, i, j)
 
-#define RDMA_SRC_I_N(addr, i)	(addr ##_reg - 0x00500000 + (0x400 * i))
-#define RDMA_SRC_O_N(addr, i)	(addr ##_reg - 0x004fc000 + (0x400 * i))
+#define RDMA_SSIU_I_P_RCAR(addr, i, j) (addr ##_reg - 0x00141000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
+#define RDMA_SSIU_O_P_RCAR(addr, i, j) RDMA_SSIU_I_N_RCAR(addr, i, j)
 
-#define RDMA_SRC_I_P(addr, i)	(addr ##_reg - 0x00200000 + (0x400 * i))
-#define RDMA_SRC_O_P(addr, i)	(addr ##_reg - 0x001fc000 + (0x400 * i))
+#define RDMA_SRC_I_N_RCAR(addr, i)	(addr ##_reg - 0x00500000 + (0x400 * i))
+#define RDMA_SRC_O_N_RCAR(addr, i)	(addr ##_reg - 0x004fc000 + (0x400 * i))
 
-#define RDMA_CMD_O_N(addr, i)	(addr ##_reg - 0x004f8000 + (0x400 * i))
-#define RDMA_CMD_O_P(addr, i)	(addr ##_reg - 0x001f8000 + (0x400 * i))
+#define RDMA_SRC_I_P_RCAR(addr, i)	(addr ##_reg - 0x00200000 + (0x400 * i))
+#define RDMA_SRC_O_P_RCAR(addr, i)	(addr ##_reg - 0x001fc000 + (0x400 * i))
+
+#define RDMA_CMD_O_N_RCAR(addr, i)	(addr ##_reg - 0x004f8000 + (0x400 * i))
+#define RDMA_CMD_O_P_RCAR(addr, i)	(addr ##_reg - 0x001f8000 + (0x400 * i))
+
+/* Platform-agnostic address macros */
+#define RDMA_SSI_I_N(p, addr, i)	rsnd_is_rzg3e(p) ? RDMA_SSI_I_N_G3E(addr, i) : RDMA_SSI_I_N_RCAR(addr, i)
+#define RDMA_SSI_O_N(p, addr, i)	rsnd_is_rzg3e(p) ? RDMA_SSI_O_N_G3E(addr, i) : RDMA_SSI_O_N_RCAR(addr, i)
+
+#define RDMA_SSIU_I_N(p, addr, i, j) rsnd_is_rzg3e(p) ? RDMA_SSIU_I_N_G3E(addr, i, j) : RDMA_SSIU_I_N_RCAR(addr, i, j)
+#define RDMA_SSIU_O_N(p, addr, i, j) rsnd_is_rzg3e(p) ? RDMA_SSIU_O_N_G3E(addr, i, j) : RDMA_SSIU_O_N_RCAR(addr, i, j)
+
+#define RDMA_SSIU_I_P(p, addr, i, j) rsnd_is_rzg3e(p) ? RDMA_SSIU_I_P_G3E(addr, i, j) : RDMA_SSIU_I_P_RCAR(addr, i, j)
+#define RDMA_SSIU_O_P(p, addr, i, j) rsnd_is_rzg3e(p) ? RDMA_SSIU_O_P_G3E(addr, i, j) : RDMA_SSIU_O_P_RCAR(addr, i, j)
+
+#define RDMA_SRC_I_N(p, addr, i)	rsnd_is_rzg3e(p) ? RDMA_SRC_I_N_G3E(addr, i) : RDMA_SRC_I_N_RCAR(addr, i)
+#define RDMA_SRC_O_N(p, addr, i)	rsnd_is_rzg3e(p) ? RDMA_SRC_O_N_G3E(addr, i) : RDMA_SRC_O_N_RCAR(addr, i)
+
+#define RDMA_SRC_I_P(p, addr, i)	rsnd_is_rzg3e(p) ? RDMA_SRC_I_P_G3E(addr, i) : RDMA_SRC_I_P_RCAR(addr, i)
+#define RDMA_SRC_O_P(p, addr, i)	rsnd_is_rzg3e(p) ? RDMA_SRC_O_P_G3E(addr, i) : RDMA_SRC_O_P_RCAR(addr, i)
+
+#define RDMA_CMD_O_N(p, addr, i)	rsnd_is_rzg3e(p) ? RDMA_CMD_O_N_G3E(addr, i) : RDMA_CMD_O_N_RCAR(addr, i)
+#define RDMA_CMD_O_P(p, addr, i)	rsnd_is_rzg3e(p) ? RDMA_CMD_O_P_G3E(addr, i) : RDMA_CMD_O_P_RCAR(addr, i)
 
 static dma_addr_t
 rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
@@ -522,8 +569,8 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
 {
 	struct rsnd_priv *priv = rsnd_io_to_priv(io);
 	struct device *dev = rsnd_priv_to_dev(priv);
-	phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_BASE_SSI);
-	phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_BASE_SCU);
+	phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, rsnd_is_rzg3e(priv) ? RSND_RZG3E_SSI : RSND_BASE_SSI);
+	phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, rsnd_is_rzg3e(priv) ? RSND_RZG3E_SCU : RSND_BASE_SCU);
 	int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod) ||
 		     !!(rsnd_io_to_mod_ssiu(io) == mod);
 	int use_src = !!rsnd_io_to_mod_src(io);
@@ -539,32 +586,32 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
 		/* SRC */
 		/* Capture */
 		{{{ 0,				0 },
-		  { RDMA_SRC_O_N(src, id),	RDMA_SRC_I_P(src, id) },
-		  { RDMA_CMD_O_N(src, id),	RDMA_SRC_I_P(src, id) } },
+		  { RDMA_SRC_O_N(priv, src, id),	RDMA_SRC_I_P(priv, src, id) },
+		  { RDMA_CMD_O_N(priv, src, id),	RDMA_SRC_I_P(priv, src, id) } },
 		 /* Playback */
 		 {{ 0,				0, },
-		  { RDMA_SRC_O_P(src, id),	RDMA_SRC_I_N(src, id) },
-		  { RDMA_CMD_O_P(src, id),	RDMA_SRC_I_N(src, id) } }
+		  { RDMA_SRC_O_P(priv, src, id),	RDMA_SRC_I_N(priv, src, id) },
+		  { RDMA_CMD_O_P(priv, src, id),	RDMA_SRC_I_N(priv, src, id) } }
 		},
 		/* SSI */
 		/* Capture */
-		{{{ RDMA_SSI_O_N(ssi, id),		0 },
-		  { RDMA_SSIU_O_P(ssi, id, busif),	0 },
-		  { RDMA_SSIU_O_P(ssi, id, busif),	0 } },
+		{{{ RDMA_SSI_O_N(priv, ssi, id),		0 },
+		  { RDMA_SSIU_O_P(priv, ssi, id, busif),	0 },
+		  { RDMA_SSIU_O_P(priv, ssi, id, busif),	0 } },
 		 /* Playback */
-		 {{ 0,			RDMA_SSI_I_N(ssi, id) },
-		  { 0,			RDMA_SSIU_I_P(ssi, id, busif) },
-		  { 0,			RDMA_SSIU_I_P(ssi, id, busif) } }
+		 {{ 0,			RDMA_SSI_I_N(priv, ssi, id) },
+		  { 0,			RDMA_SSIU_I_P(priv, ssi, id, busif) },
+		  { 0,			RDMA_SSIU_I_P(priv, ssi, id, busif) } }
 		},
 		/* SSIU */
 		/* Capture */
-		{{{ RDMA_SSIU_O_N(ssi, id, busif),	0 },
-		  { RDMA_SSIU_O_P(ssi, id, busif),	0 },
-		  { RDMA_SSIU_O_P(ssi, id, busif),	0 } },
+		{{{ RDMA_SSIU_O_N(priv, ssi, id, busif),	0 },
+		  { RDMA_SSIU_O_P(priv, ssi, id, busif),	0 },
+		  { RDMA_SSIU_O_P(priv, ssi, id, busif),	0 } },
 		 /* Playback */
-		 {{ 0,			RDMA_SSIU_I_N(ssi, id, busif) },
-		  { 0,			RDMA_SSIU_I_P(ssi, id, busif) },
-		  { 0,			RDMA_SSIU_I_P(ssi, id, busif) } } },
+		 {{ 0,			RDMA_SSIU_I_N(priv, ssi, id, busif) },
+		  { 0,			RDMA_SSIU_I_P(priv, ssi, id, busif) },
+		  { 0,			RDMA_SSIU_I_P(priv, ssi, id, busif) } } },
 	};
 
 	/*
@@ -803,8 +850,12 @@ static int rsnd_dma_alloc(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
 
 	*dma_mod = rsnd_mod_get(dma);
 
-	ret = rsnd_mod_init(priv, *dma_mod, ops, NULL, NULL,
-			    type, dma_id);
+	/*
+	 * Pass NULL for clock/reset - audmac_pp is managed globally in
+	 * rsnd_dma_probe() and core.c suspend/resume, not per-DMA-module.
+	 * See detailed explanation in rsnd_dma_probe().
+	 */
+	ret = rsnd_mod_init(priv, *dma_mod, ops, NULL, NULL, type, dma_id);
 	if (ret < 0)
 		return ret;
 
@@ -838,6 +889,12 @@ int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
 	return rsnd_dai_connect(*dma_mod, io, (*dma_mod)->type);
 }
 
+void rsnd_dma_detach(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
+		     struct rsnd_mod **dma_mod)
+{
+	rsnd_dai_disconnect(*dma_mod, io, (*dma_mod)->type);
+}
+
 int rsnd_dma_probe(struct rsnd_priv *priv)
 {
 	struct platform_device *pdev = rsnd_priv_to_pdev(priv);
@@ -860,6 +917,56 @@ int rsnd_dma_probe(struct rsnd_priv *priv)
 		return 0; /* it will be PIO mode */
 	}
 
+	/*
+	 * audmac_pp clock/reset management strategy:
+	 *
+	 * Unlike other modules (SSI, SRC, etc.) which have their own dedicated
+	 * clocks, all DMA modules share the single audmac_pp clock/reset.
+	 * Managing it per-stream or per-DMA-module causes
+	 * reference count imbalances:
+	 *
+	 *   - rsnd_mod_init() does clk_prepare_enable() then clk_disable(),
+	 *     leaving prepare_count=1 per module
+	 *   - With N DMA modules sharing the same clock handle, prepare_count=N
+	 *   - suspend does single clk_disable_unprepare() (-1)
+	 *   - resume does single clk_prepare_enable() (+1)
+	 *   - Result: prepare_count leaks on each suspend/resume cycle
+	 *
+	 * Per-stream management (iterating DMA modules in suspend/resume) is
+	 * not worth the complexity:
+	 *
+	 *   - No power benefit: audmac_pp is needed whenever ANY stream is
+	 *     active, and every stream uses DMA, so it's essentially always on
+	 *   - Architecture mismatch: DMA modules live in io->dma, not in a
+	 *     priv array -- no clean way to iterate like SSI/SRC/DVC
+	 *   - Shared handle problem: all DMA modules point to the same clock,
+	 *     so iterating would call clk_unprepare() N times on one clock
+	 *   - Would require manual refcounting ("enable on first stream,
+	 *     disable on last") -- reimplementing what clk framework does
+	 *
+	 * The correct approach is to treat audmac_pp as always-on infrastructure
+	 * (same pattern as clk_adg), managed globally:
+	 *   - Probe: acquire + enable (via devm_clk_get_optional_enabled)
+	 *   - Suspend/Resume: toggle in core.c rsnd_suspend/rsnd_resume
+	 *   - Remove: devm cleanup
+	 *   - DMA modules: pass NULL clock/reset to rsnd_mod_init()
+	 *
+	 * Use devm variants that handle deassert/enable automatically.
+	 * Order: reset deasserted first, then clock enabled.
+	 */
+	priv->rstc_audmac_pp =
+		devm_reset_control_get_optional_exclusive_deasserted(dev, "audmac_pp");
+	if (IS_ERR(priv->rstc_audmac_pp)) {
+		return dev_err_probe(dev, PTR_ERR(priv->rstc_audmac_pp),
+				     "failed to get audmac_pp reset\n");
+	}
+
+	priv->clk_audmac_pp = devm_clk_get_optional_enabled(dev, "audmac_pp");
+	if (IS_ERR(priv->clk_audmac_pp)) {
+		return dev_err_probe(dev, PTR_ERR(priv->clk_audmac_pp),
+				     "failed to get audmac_pp clock\n");
+	}
+
 	/* for Gen4 doesn't have DMA-pp */
 	if (rsnd_is_gen4(priv))
 		goto audmapp_end;
diff --git a/sound/soc/renesas/rcar/rsnd.h b/sound/soc/renesas/rcar/rsnd.h
index 173fe475b7f8..8f3637904884 100644
--- a/sound/soc/renesas/rcar/rsnd.h
+++ b/sound/soc/renesas/rcar/rsnd.h
@@ -271,6 +271,8 @@ u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod);
  */
 int rsnd_dma_attach(struct rsnd_dai_stream *io,
 		    struct rsnd_mod *mod, struct rsnd_mod **dma_mod);
+void rsnd_dma_detach(struct rsnd_dai_stream *io,
+		     struct rsnd_mod *mod, struct rsnd_mod **dma_mod);
 int rsnd_dma_probe(struct rsnd_priv *priv);
 struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node, char *name,
 					  struct rsnd_mod *mod, char *x);
@@ -590,6 +592,9 @@ int rsnd_rdai_width_ctrl(struct rsnd_dai *rdai, int width);
 int rsnd_dai_connect(struct rsnd_mod *mod,
 		     struct rsnd_dai_stream *io,
 		     enum rsnd_mod_type type);
+void rsnd_dai_disconnect(struct rsnd_mod *mod,
+			 struct rsnd_dai_stream *io,
+			 enum rsnd_mod_type type);
 
 /*
  *	R-Car Gen1/Gen2
@@ -628,6 +633,13 @@ void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct seq_file *m);
 struct rsnd_priv {
 
 	struct platform_device *pdev;
+
+	/*
+	 * below value will be filled on rsnd_dma_probe()
+	 */
+	struct clk *clk_audmac_pp;
+	struct reset_control *rstc_audmac_pp;
+
 	spinlock_t lock;
 	unsigned long flags;
 #define RSND_GEN_MASK	(0xF << 0)
-- 
2.25.1
Re: [PATCH 10/22] ASoC: rsnd: Add DMA support infrastructure for RZ/G3E
Posted by Kuninori Morimoto 2 weeks ago
Hi John

> RZ/G3E has different DMA register base addresses and offset calculations
> compared to R-Car platforms, and requires additional audmac-pp clock and
> reset lines for Audio DMAC operation.
> 
> Add RZ/G3E-specific DMA address macros and audmac-pp clock/reset support
> using optional APIs to remain transparent to other platforms.
> 
> Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
> ---
(snip)
> -	ret = rsnd_mod_init(priv, *dma_mod, ops, NULL, NULL,
> -			    type, dma_id);
> +	/*
> +	 * Pass NULL for clock/reset - audmac_pp is managed globally in
> +	 * rsnd_dma_probe() and core.c suspend/resume, not per-DMA-module.
> +	 * See detailed explanation in rsnd_dma_probe().
> +	 */
> +	ret = rsnd_mod_init(priv, *dma_mod, ops, NULL, NULL, type, dma_id);
>  	if (ret < 0)
>  		return ret;

This patch change rsnd_mod_init() parameters independently.
Is this patch-set can keep compile comapatible ??

Thank you for your help !!

Best regards
---
Kuninori Morimoto
Re: [PATCH 10/22] ASoC: rsnd: Add DMA support infrastructure for RZ/G3E
Posted by Kuninori Morimoto 2 weeks ago
Hi John

Thank you for your patch

> RZ/G3E has different DMA register base addresses and offset calculations
> compared to R-Car platforms, and requires additional audmac-pp clock and
> reset lines for Audio DMAC operation.
> 
> Add RZ/G3E-specific DMA address macros and audmac-pp clock/reset support
> using optional APIs to remain transparent to other platforms.
> 
> Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
> ---

I think it include many features in 1 patch.
You should separate it into each features.

> diff --git a/sound/soc/renesas/rcar/dma.c b/sound/soc/renesas/rcar/dma.c
> index 68c859897e68..d3123ae3b402 100644
> --- a/sound/soc/renesas/rcar/dma.c
> +++ b/sound/soc/renesas/rcar/dma.c
> @@ -496,24 +496,71 @@ static struct rsnd_mod_ops rsnd_dmapp_ops = {
>   *	SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000
>   *	SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000
>   *	CMD : 0xec500000 /            / 0xec008000                0xec308000
> + *
> + * 	ex) G3E case
> + *	      mod        / DMAC in    / DMAC out   / DMAC PP in / DMAC pp out
> + *	SSI : 0x13C31000 / 0x13C40000 / 0x13C40000
> + *	SSIU: 0x13C31000 / 0x13C40000 / 0x13C40000 / 0xEC400000 / 0xEC400000
> + *	SCU : 0x13C00000 / 0x13C10000 / 0x13C14000 / 0xEC300000 / 0xEC304000
> + *	CMD : 0x13C00000 /            / 0x13C18000                0xEC308000
>   */
> -#define RDMA_SSI_I_N(addr, i)	(addr ##_reg - 0x00300000 + (0x40 * i) + 0x8)
> -#define RDMA_SSI_O_N(addr, i)	(addr ##_reg - 0x00300000 + (0x40 * i) + 0xc)
>  
> -#define RDMA_SSIU_I_N(addr, i, j) (addr ##_reg - 0x00441000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
> -#define RDMA_SSIU_O_N(addr, i, j) RDMA_SSIU_I_N(addr, i, j)
> +/* RZ/G3E DMA address macros */
> +#define RDMA_SSI_I_N_G3E(addr, i)	(addr ##_reg + 0x0000F000 + (0x1000 * i))
> +#define RDMA_SSI_O_N_G3E(addr, i)	(addr ##_reg + 0x0000F000 + (0x1000 * i))
> +
> +#define RDMA_SSIU_I_N_G3E(addr, i, j) (addr ##_reg + 0x0000F000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
> +#define RDMA_SSIU_O_N_G3E(addr, i, j) RDMA_SSIU_I_N_G3E(addr, i, j)
> +
> +#define RDMA_SSIU_I_P_G3E(addr, i, j) (addr ##_reg + 0xD87CF000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
> +#define RDMA_SSIU_O_P_G3E(addr, i, j) RDMA_SSIU_I_P_G3E(addr, i, j)
> +
> +#define RDMA_SRC_I_N_G3E(addr, i)	(addr ##_reg + 0x00010000 + (0x400 * i))
> +#define RDMA_SRC_O_N_G3E(addr, i)	(addr ##_reg + 0x00014000 + (0x400 * i))
> +
> +#define RDMA_SRC_I_P_G3E(addr, i)	(addr ##_reg + 0xD8700000 + (0x400 * i))
> +#define RDMA_SRC_O_P_G3E(addr, i)	(addr ##_reg + 0xD8704000 + (0x400 * i))
> +
> +#define RDMA_CMD_O_N_G3E(addr, i)	(addr ##_reg + 0x00018000 + (0x400 * i))
> +#define RDMA_CMD_O_P_G3E(addr, i)	(addr ##_reg + 0xD8708000 + (0x400 * i))
> +
> +/* R-Car DMA address macros */
> +#define RDMA_SSI_I_N_RCAR(addr, i)	(addr ##_reg - 0x00300000 + (0x40 * i) + 0x8)
> +#define RDMA_SSI_O_N_RCAR(addr, i)	(addr ##_reg - 0x00300000 + (0x40 * i) + 0xc)
>  
> -#define RDMA_SSIU_I_P(addr, i, j) (addr ##_reg - 0x00141000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
> -#define RDMA_SSIU_O_P(addr, i, j) RDMA_SSIU_I_P(addr, i, j)
> +#define RDMA_SSIU_I_N_RCAR(addr, i, j) (addr ##_reg - 0x00441000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
> +#define RDMA_SSIU_O_N_RCAR(addr, i, j) RDMA_SSIU_I_N_RCAR(addr, i, j)
>  
> -#define RDMA_SRC_I_N(addr, i)	(addr ##_reg - 0x00500000 + (0x400 * i))
> -#define RDMA_SRC_O_N(addr, i)	(addr ##_reg - 0x004fc000 + (0x400 * i))
> +#define RDMA_SSIU_I_P_RCAR(addr, i, j) (addr ##_reg - 0x00141000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
> +#define RDMA_SSIU_O_P_RCAR(addr, i, j) RDMA_SSIU_I_N_RCAR(addr, i, j)
>  
> -#define RDMA_SRC_I_P(addr, i)	(addr ##_reg - 0x00200000 + (0x400 * i))
> -#define RDMA_SRC_O_P(addr, i)	(addr ##_reg - 0x001fc000 + (0x400 * i))
> +#define RDMA_SRC_I_N_RCAR(addr, i)	(addr ##_reg - 0x00500000 + (0x400 * i))
> +#define RDMA_SRC_O_N_RCAR(addr, i)	(addr ##_reg - 0x004fc000 + (0x400 * i))
>  
> -#define RDMA_CMD_O_N(addr, i)	(addr ##_reg - 0x004f8000 + (0x400 * i))
> -#define RDMA_CMD_O_P(addr, i)	(addr ##_reg - 0x001f8000 + (0x400 * i))
> +#define RDMA_SRC_I_P_RCAR(addr, i)	(addr ##_reg - 0x00200000 + (0x400 * i))
> +#define RDMA_SRC_O_P_RCAR(addr, i)	(addr ##_reg - 0x001fc000 + (0x400 * i))
> +
> +#define RDMA_CMD_O_N_RCAR(addr, i)	(addr ##_reg - 0x004f8000 + (0x400 * i))
> +#define RDMA_CMD_O_P_RCAR(addr, i)	(addr ##_reg - 0x001f8000 + (0x400 * i))
> +
> +/* Platform-agnostic address macros */
> +#define RDMA_SSI_I_N(p, addr, i)	rsnd_is_rzg3e(p) ? RDMA_SSI_I_N_G3E(addr, i) : RDMA_SSI_I_N_RCAR(addr, i)
> +#define RDMA_SSI_O_N(p, addr, i)	rsnd_is_rzg3e(p) ? RDMA_SSI_O_N_G3E(addr, i) : RDMA_SSI_O_N_RCAR(addr, i)
> +
> +#define RDMA_SSIU_I_N(p, addr, i, j) rsnd_is_rzg3e(p) ? RDMA_SSIU_I_N_G3E(addr, i, j) : RDMA_SSIU_I_N_RCAR(addr, i, j)
> +#define RDMA_SSIU_O_N(p, addr, i, j) rsnd_is_rzg3e(p) ? RDMA_SSIU_O_N_G3E(addr, i, j) : RDMA_SSIU_O_N_RCAR(addr, i, j)
> +
> +#define RDMA_SSIU_I_P(p, addr, i, j) rsnd_is_rzg3e(p) ? RDMA_SSIU_I_P_G3E(addr, i, j) : RDMA_SSIU_I_P_RCAR(addr, i, j)
> +#define RDMA_SSIU_O_P(p, addr, i, j) rsnd_is_rzg3e(p) ? RDMA_SSIU_O_P_G3E(addr, i, j) : RDMA_SSIU_O_P_RCAR(addr, i, j)
> +
> +#define RDMA_SRC_I_N(p, addr, i)	rsnd_is_rzg3e(p) ? RDMA_SRC_I_N_G3E(addr, i) : RDMA_SRC_I_N_RCAR(addr, i)
> +#define RDMA_SRC_O_N(p, addr, i)	rsnd_is_rzg3e(p) ? RDMA_SRC_O_N_G3E(addr, i) : RDMA_SRC_O_N_RCAR(addr, i)
> +
> +#define RDMA_SRC_I_P(p, addr, i)	rsnd_is_rzg3e(p) ? RDMA_SRC_I_P_G3E(addr, i) : RDMA_SRC_I_P_RCAR(addr, i)
> +#define RDMA_SRC_O_P(p, addr, i)	rsnd_is_rzg3e(p) ? RDMA_SRC_O_P_G3E(addr, i) : RDMA_SRC_O_P_RCAR(addr, i)
> +
> +#define RDMA_CMD_O_N(p, addr, i)	rsnd_is_rzg3e(p) ? RDMA_CMD_O_N_G3E(addr, i) : RDMA_CMD_O_N_RCAR(addr, i)
> +#define RDMA_CMD_O_P(p, addr, i)	rsnd_is_rzg3e(p) ? RDMA_CMD_O_P_G3E(addr, i) : RDMA_CMD_O_P_RCAR(addr, i)

I think you want to create new rsnd_rzg3e_dma_addr() and call it,
instead of makes existing code complex.

+ static dma_addr_t rsnd_rzg3e_dma_addr(...)
+ {
+	...
+ }
...
  static dma_addr_t rsnd_dma_addr(...)
  {
	...
	else if (rsnd_is_gen4(priv))
		return rsnd_gen4_dma_addr(...);
+	else if (rsnd_is_rzg3e(priv))
+		return rsnd_rzg3e_dma_addr(...)
	else
		return rsnd_gen2_dma_addr(...);
}

> @@ -860,6 +917,56 @@ int rsnd_dma_probe(struct rsnd_priv *priv)
>  		return 0; /* it will be PIO mode */
>  	}
>  
> +	/*
> +	 * audmac_pp clock/reset management strategy:
> +	 *
> +	 * Unlike other modules (SSI, SRC, etc.) which have their own dedicated
> +	 * clocks, all DMA modules share the single audmac_pp clock/reset.
> +	 * Managing it per-stream or per-DMA-module causes
> +	 * reference count imbalances:
> +	 *
> +	 *   - rsnd_mod_init() does clk_prepare_enable() then clk_disable(),
> +	 *     leaving prepare_count=1 per module
> +	 *   - With N DMA modules sharing the same clock handle, prepare_count=N
> +	 *   - suspend does single clk_disable_unprepare() (-1)
> +	 *   - resume does single clk_prepare_enable() (+1)
> +	 *   - Result: prepare_count leaks on each suspend/resume cycle
> +	 *
> +	 * Per-stream management (iterating DMA modules in suspend/resume) is
> +	 * not worth the complexity:
> +	 *
> +	 *   - No power benefit: audmac_pp is needed whenever ANY stream is
> +	 *     active, and every stream uses DMA, so it's essentially always on
> +	 *   - Architecture mismatch: DMA modules live in io->dma, not in a
> +	 *     priv array -- no clean way to iterate like SSI/SRC/DVC
> +	 *   - Shared handle problem: all DMA modules point to the same clock,
> +	 *     so iterating would call clk_unprepare() N times on one clock
> +	 *   - Would require manual refcounting ("enable on first stream,
> +	 *     disable on last") -- reimplementing what clk framework does
> +	 *
> +	 * The correct approach is to treat audmac_pp as always-on infrastructure
> +	 * (same pattern as clk_adg), managed globally:
> +	 *   - Probe: acquire + enable (via devm_clk_get_optional_enabled)
> +	 *   - Suspend/Resume: toggle in core.c rsnd_suspend/rsnd_resume
> +	 *   - Remove: devm cleanup
> +	 *   - DMA modules: pass NULL clock/reset to rsnd_mod_init()
> +	 *
> +	 * Use devm variants that handle deassert/enable automatically.
> +	 * Order: reset deasserted first, then clock enabled.
> +	 */
> +	priv->rstc_audmac_pp =
> +		devm_reset_control_get_optional_exclusive_deasserted(dev, "audmac_pp");
> +	if (IS_ERR(priv->rstc_audmac_pp)) {
> +		return dev_err_probe(dev, PTR_ERR(priv->rstc_audmac_pp),
> +				     "failed to get audmac_pp reset\n");
> +	}
> +
> +	priv->clk_audmac_pp = devm_clk_get_optional_enabled(dev, "audmac_pp");
> +	if (IS_ERR(priv->clk_audmac_pp)) {
> +		return dev_err_probe(dev, PTR_ERR(priv->clk_audmac_pp),
> +				     "failed to get audmac_pp clock\n");
> +	}

rsnd_dma_probe() is common fucntion.
Is above possible to keep compatible with other SoCs ?

And, we are already using "audmacpp".
I think it time to update rsnd_dma_probe() like below ?

	int rsnd_dma_probe(...)
	{
		if (rsnd_is_gen1(..))
			return ...
		else if (rsnd_is_gen2(...) ||
			 rsnd_is_gen3(...))
			return ...
		else if (rsnd_is_gen4(...))
			return ...
		else if (rsnd_is_rzg3e(...))
			return ...
		...
	}