[PATCH v7 15/18] ASoC: rsnd: src: Acquire shared SCU clocks for RZ/G3E

From: John Madieu

Date: Mon May 25 2026 - 07:06:06 EST


The RZ/G3E SoC requires explicit SCU (Sampling Rate Converter Unit)
clock management:

- scu: SCU top-level module clock (CPG_CLKON_15.CLK6_ON)
- scu_x2: SCU top-level double-rate clock (CPG_CLKON_15.CLK7_ON)
- scu_supply: SCU register-access / housekeeping clock
(CPG_CLKON_23.CLK14_ON)

Without every one of them enabled, no SCU register is reachable.

Hold these in a new struct rsnd_src_ctrl and acquire them with
devm_clk_get_optional_enabled(). scu_supply is intentionally left
untouched by the system suspend/resume path added later in the
series, so SCU registers stay reachable across PM transitions.

Signed-off-by: John Madieu <john.madieu.xa@xxxxxxxxxxxxxx>
---

Changes:

v7: New patch. Split out of [PATCH v6 14/16] "ASoC: rsnd: src: Add
SRC reset and clock support for RZ/G3E" per Kuninori Morimoto's
request that the SCU clock and the SCU reset be independent
changes. This patch carries only struct rsnd_src_ctrl and the
scu / scu_x2 / scu_supply acquisition via
devm_clk_get_optional_enabled(), so non-RZ/G3E DTs are
unaffected.

sound/soc/renesas/rcar/rsnd.h | 1 +
sound/soc/renesas/rcar/src.c | 37 +++++++++++++++++++++++++++++++++++
2 files changed, 38 insertions(+)

diff --git a/sound/soc/renesas/rcar/rsnd.h b/sound/soc/renesas/rcar/rsnd.h
index 95843a20c43c..7d7da6cecf09 100644
--- a/sound/soc/renesas/rcar/rsnd.h
+++ b/sound/soc/renesas/rcar/rsnd.h
@@ -698,6 +698,7 @@ struct rsnd_priv {
/*
* below value will be filled on rsnd_src_probe()
*/
+ void *src_ctrl;
void *src;
int src_nr;

diff --git a/sound/soc/renesas/rcar/src.c b/sound/soc/renesas/rcar/src.c
index 43abe13137bf..88ea9aad5cae 100644
--- a/sound/soc/renesas/rcar/src.c
+++ b/sound/soc/renesas/rcar/src.c
@@ -53,6 +53,14 @@ struct rsnd_src {
((pos) = (struct rsnd_src *)(priv)->src + i); \
i++)

+struct rsnd_src_ctrl {
+ struct clk *scu;
+ struct clk *scu_x2;
+ struct clk *scu_supply;
+};
+
+#define rsnd_priv_to_src_ctrl(priv) \
+ ((struct rsnd_src_ctrl *)(priv)->src_ctrl)

/*
* image of SRC (Sampling Rate Converter)
@@ -712,6 +720,7 @@ int rsnd_src_probe(struct rsnd_priv *priv)
{
struct device_node *node;
struct device *dev = rsnd_priv_to_dev(priv);
+ struct rsnd_src_ctrl *src_ctrl;
struct rsnd_src *src;
struct clk *clk;
int i, nr, ret;
@@ -726,6 +735,12 @@ int rsnd_src_probe(struct rsnd_priv *priv)
goto rsnd_src_probe_done;
}

+ src_ctrl = devm_kzalloc(dev, sizeof(*src_ctrl), GFP_KERNEL);
+ if (!src_ctrl) {
+ ret = -ENOMEM;
+ goto rsnd_src_probe_done;
+ }
+
src = devm_kcalloc(dev, nr, sizeof(*src), GFP_KERNEL);
if (!src) {
ret = -ENOMEM;
@@ -734,6 +749,28 @@ int rsnd_src_probe(struct rsnd_priv *priv)

priv->src_nr = nr;
priv->src = src;
+ priv->src_ctrl = src_ctrl;
+
+ src_ctrl->scu = devm_clk_get_optional_enabled(dev, "scu");
+ if (IS_ERR(src_ctrl->scu)) {
+ ret = dev_err_probe(dev, PTR_ERR(src_ctrl->scu),
+ "failed to get scu clock\n");
+ goto rsnd_src_probe_done;
+ }
+
+ src_ctrl->scu_x2 = devm_clk_get_optional_enabled(dev, "scu_x2");
+ if (IS_ERR(src_ctrl->scu_x2)) {
+ ret = dev_err_probe(dev, PTR_ERR(src_ctrl->scu_x2),
+ "failed to get scu_x2 clock\n");
+ goto rsnd_src_probe_done;
+ }
+
+ src_ctrl->scu_supply = devm_clk_get_optional_enabled(dev, "scu_supply");
+ if (IS_ERR(src_ctrl->scu_supply)) {
+ ret = dev_err_probe(dev, PTR_ERR(src_ctrl->scu_supply),
+ "failed to get scu_supply clock\n");
+ goto rsnd_src_probe_done;
+ }

i = 0;
for_each_child_of_node_scoped(node, np) {
--
2.25.1