[PATCH 15/22] ASoC: rsnd: src: Add SRC reset and clock support for RZ/G3E

John Madieu posted 22 patches 2 weeks, 3 days ago
There is a newer version of this series
[PATCH 15/22] ASoC: rsnd: src: Add SRC reset and clock support for RZ/G3E
Posted by John Madieu 2 weeks, 3 days ago
The RZ/G3E SoC requires explicit SCU (Sampling Rate Converter Unit)
reset and clock management unlike previous R-Car generations:

- scu_clk: SCU module clock
- scu_clkx2: SCU double-rate clock
- scu_supply_clk: SCU supply clock

Without these clocks enabled, the SRC module cannot operate on RZ/G3E.
Add support for the shared SCU reset controller used by the SRC modules
on the Renesas RZ/G3E SoC. All SRC instances are gated by the same "scu"
reset line.

Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
---
 sound/soc/renesas/rcar/rsnd.h |  7 ++++++
 sound/soc/renesas/rcar/src.c  | 45 +++++++++++++++++++++++++++++++++--
 2 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/sound/soc/renesas/rcar/rsnd.h b/sound/soc/renesas/rcar/rsnd.h
index 6bde304f93a8..a803c0f03665 100644
--- a/sound/soc/renesas/rcar/rsnd.h
+++ b/sound/soc/renesas/rcar/rsnd.h
@@ -642,6 +642,13 @@ struct rsnd_priv {
 	struct clk *clk_audmac_pp;
 	struct reset_control *rstc_audmac_pp;
 
+	/*
+	 * Below values will be filled in rsnd_src_probe()
+	 */
+	struct clk *clk_scu;
+	struct clk *clk_scu_x2;
+	struct clk *clk_scu_supply;
+
 	spinlock_t lock;
 	unsigned int ssiu_busif_count;
 	unsigned long flags;
diff --git a/sound/soc/renesas/rcar/src.c b/sound/soc/renesas/rcar/src.c
index 8b58cc20e7a8..e1f609589406 100644
--- a/sound/soc/renesas/rcar/src.c
+++ b/sound/soc/renesas/rcar/src.c
@@ -516,6 +516,7 @@ static int rsnd_src_init(struct rsnd_mod *mod,
 			 struct rsnd_priv *priv)
 {
 	struct rsnd_src *src = rsnd_mod_to_src(mod);
+	struct device *dev = rsnd_priv_to_dev(priv);
 	int ret;
 
 	/* reset sync convert_rate */
@@ -526,6 +527,12 @@ static int rsnd_src_init(struct rsnd_mod *mod,
 	if (ret < 0)
 		return ret;
 
+	ret = clk_prepare_enable(priv->clk_scu_supply);
+	if (ret) {
+		dev_err(dev, "Cannot enable scu_supply_clk\n");
+		return ret;
+	}
+
 	rsnd_src_activation(mod);
 
 	rsnd_src_init_convert_rate(io, mod);
@@ -549,6 +556,8 @@ static int rsnd_src_quit(struct rsnd_mod *mod,
 	src->sync.val		=
 	src->current_sync_rate	= 0;
 
+	clk_disable_unprepare(priv->clk_scu_supply);
+
 	return 0;
 }
 
@@ -711,8 +720,9 @@ struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id)
 
 int rsnd_src_probe(struct rsnd_priv *priv)
 {
-	struct device_node *node;
 	struct device *dev = rsnd_priv_to_dev(priv);
+	struct reset_control *rstc;
+	struct device_node *node;
 	struct rsnd_src *src;
 	struct clk *clk;
 	char name[RSND_SRC_NAME_SIZE];
@@ -737,6 +747,27 @@ int rsnd_src_probe(struct rsnd_priv *priv)
 	priv->src_nr	= nr;
 	priv->src	= src;
 
+	priv->clk_scu = devm_clk_get_optional_enabled(dev, "scu");
+	if (IS_ERR(priv->clk_scu)) {
+		ret = dev_err_probe(dev, PTR_ERR(priv->clk_scu),
+				    "failed to get scu clock\n");
+		goto rsnd_src_probe_done;
+	}
+
+	priv->clk_scu_x2 = devm_clk_get_optional_enabled(dev, "scu_x2");
+	if (IS_ERR(priv->clk_scu_x2)) {
+		ret = dev_err_probe(dev, PTR_ERR(priv->clk_scu_x2),
+				    "failed to get scu_x2 clock\n");
+		goto rsnd_src_probe_done;
+	}
+
+	priv->clk_scu_supply = devm_clk_get_optional(dev, "scu_supply");
+	if (IS_ERR(priv->clk_scu_supply)) {
+		ret = dev_err_probe(dev, PTR_ERR(priv->clk_scu_supply),
+				    "failed to get scu_supply clock\n");
+		goto rsnd_src_probe_done;
+	}
+
 	i = 0;
 	for_each_child_of_node_scoped(node, np) {
 		if (!of_device_is_available(np))
@@ -759,6 +790,16 @@ int rsnd_src_probe(struct rsnd_priv *priv)
 			goto rsnd_src_probe_done;
 		}
 
+		/*
+		 * RZ/G3E uses a shared SCU reset controller for all SRC modules.
+		 * R-Car platforms typically don't have SRC reset controls.
+		 */
+		rstc = devm_reset_control_get_optional_shared(dev, "scu");
+		if (IS_ERR(rstc)) {
+			ret = PTR_ERR(rstc);
+			goto rsnd_src_probe_done;
+		}
+
 		clk = devm_clk_get(dev, name);
 		if (IS_ERR(clk)) {
 			ret = PTR_ERR(clk);
@@ -766,7 +807,7 @@ int rsnd_src_probe(struct rsnd_priv *priv)
 		}
 
 		ret = rsnd_mod_init(priv, rsnd_mod_get(src),
-				    &rsnd_src_ops, clk, NULL, RSND_MOD_SRC, i);
+				    &rsnd_src_ops, clk, rstc, RSND_MOD_SRC, i);
 		if (ret)
 			goto rsnd_src_probe_done;
 
-- 
2.25.1