[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260128125850.425264-5-biju.das.jz@bp.renesas.com>
Date: Wed, 28 Jan 2026 12:58:41 +0000
From: Biju <biju.das.au@...il.com>
To: Geert Uytterhoeven <geert+renesas@...der.be>,
Michael Turquette <mturquette@...libre.com>,
Stephen Boyd <sboyd@...nel.org>
Cc: Biju Das <biju.das.jz@...renesas.com>,
linux-renesas-soc@...r.kernel.org,
linux-clk@...r.kernel.org,
linux-kernel@...r.kernel.org,
Prabhakar Mahadev Lad <prabhakar.mahadev-lad.rj@...renesas.com>,
Biju Das <biju.das.au@...il.com>
Subject: [PATCH net-next 4/8] clk: renesas: rzg2l: Add support for enabling PLLs
From: Biju Das <biju.das.jz@...renesas.com>
Add support for enabling PLL clocks in the RZ/G3L CPG driver to turn off
some PLLs, if they are not in use(eg: PLL6, PLL7)
Introduce `is_enabled` and `enable` callbacks to handle PLL state
transitions. With the `enable` callback, PLL will be turned ON only when
the PLL consumer device is enabled; otherwise, it will remain off. Define
new macros for PLL standby and monitor registers to facilitate this
process.
Signed-off-by: Biju Das <biju.das.jz@...renesas.com>
---
drivers/clk/renesas/rzg2l-cpg.c | 67 +++++++++++++++++++++++++++++++++
drivers/clk/renesas/rzg2l-cpg.h | 4 ++
2 files changed, 71 insertions(+)
diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
index ee92d07c6ff7..dfb36e6e6a7b 100644
--- a/drivers/clk/renesas/rzg2l-cpg.c
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -58,6 +58,13 @@
#define RZG3S_DIV_NF GENMASK(12, 1)
#define RZG3S_SEL_PLL BIT(0)
+#define RZG3L_PLL_STBY_OFFSET(x) (GET_REG_SAMPLL_CLK1(x) - 0x4)
+#define RZG3L_PLL_STBY_RESETB BIT(0)
+#define RZG3L_PLL_STBY_RESETB_WEN BIT(16)
+#define RZG3L_PLL_MON_OFFSET(x) (GET_REG_SAMPLL_CLK1(x) + 0x8)
+#define RZG3L_PLL_MON_RESETB BIT(0)
+#define RZG3L_PLL_MON_LOCK BIT(4)
+
#define CLK_ON_R(reg) (reg)
#define CLK_MON_R(reg) (0x180 + (reg))
#define CLK_RST_R(reg) (reg)
@@ -1181,6 +1188,63 @@ rzg2l_cpg_pll_clk_register(const struct cpg_core_clk *core,
return pll_clk->hw.clk;
}
+static int rzg3l_cpg_pll_clk_is_enabled(struct clk_hw *hw)
+{
+ struct pll_clk *pll_clk = to_pll(hw);
+ struct rzg2l_cpg_priv *priv = pll_clk->priv;
+ u32 val = readl(priv->base + RZG3L_PLL_MON_OFFSET(pll_clk->conf));
+ u32 mon_val = RZG3L_PLL_MON_RESETB | RZG3L_PLL_MON_LOCK;
+
+ /* Ensure both RESETB and LOCK bits are set */
+ return (mon_val == (val & mon_val));
+}
+
+static int rzg3l_cpg_pll_clk_endisable(struct clk_hw *hw, bool enable)
+{
+ struct pll_clk *pll_clk = to_pll(hw);
+ struct rzg2l_cpg_priv *priv = pll_clk->priv;
+ u32 stby_offset, mon_offset;
+ u32 val, mon_val;
+ int ret;
+
+ stby_offset = RZG3L_PLL_STBY_OFFSET(pll_clk->conf);
+ mon_offset = RZG3L_PLL_MON_OFFSET(pll_clk->conf);
+
+ if (enable) {
+ val = RZG3L_PLL_STBY_RESETB_WEN | RZG3L_PLL_STBY_RESETB;
+ mon_val = RZG3L_PLL_MON_RESETB | RZG3L_PLL_MON_LOCK;
+ } else {
+ val = RZG3L_PLL_STBY_RESETB_WEN;
+ mon_val = 0;
+ }
+
+ writel(val, priv->base + stby_offset);
+
+ /* ensure PLL is in normal/stanby mode */
+ ret = readl_poll_timeout_atomic(priv->base + mon_offset, val, mon_val ==
+ (val & (RZG3L_PLL_MON_RESETB | RZG3L_PLL_MON_LOCK)),
+ 10, 100);
+ if (ret)
+ dev_err(priv->dev, "Failed to %s PLL 0x%x/%pC\n", enable ?
+ "enable" : "disable", stby_offset, hw->clk);
+
+ return ret;
+}
+
+static int rzg3l_cpg_pll_clk_enable(struct clk_hw *hw)
+{
+ if (rzg3l_cpg_pll_clk_is_enabled(hw))
+ return 0;
+
+ return rzg3l_cpg_pll_clk_endisable(hw, true);
+}
+
+static const struct clk_ops rzg3l_cpg_pll_ops = {
+ .is_enabled = rzg3l_cpg_pll_clk_is_enabled,
+ .enable = rzg3l_cpg_pll_clk_enable,
+ .recalc_rate = rzg3s_cpg_pll_clk_recalc_rate,
+};
+
static struct clk
*rzg2l_cpg_clk_src_twocell_get(struct of_phandle_args *clkspec,
void *data)
@@ -1264,6 +1328,9 @@ rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core,
case CLK_TYPE_SAM_PLL:
clk = rzg2l_cpg_pll_clk_register(core, priv, &rzg2l_cpg_pll_ops);
break;
+ case CLK_TYPE_G3L_PLL:
+ clk = rzg2l_cpg_pll_clk_register(core, priv, &rzg3l_cpg_pll_ops);
+ break;
case CLK_TYPE_G3S_PLL:
clk = rzg2l_cpg_pll_clk_register(core, priv, &rzg3s_cpg_pll_ops);
break;
diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h
index 1db413bb433d..7de4cb7af1cc 100644
--- a/drivers/clk/renesas/rzg2l-cpg.h
+++ b/drivers/clk/renesas/rzg2l-cpg.h
@@ -123,6 +123,7 @@ enum clk_types {
CLK_TYPE_IN, /* External Clock Input */
CLK_TYPE_FF, /* Fixed Factor Clock */
CLK_TYPE_SAM_PLL,
+ CLK_TYPE_G3L_PLL,
CLK_TYPE_G3S_PLL,
/* Clock with divider */
@@ -152,6 +153,9 @@ enum clk_types {
DEF_TYPE(_name, _id, _type, .parent = _parent)
#define DEF_SAMPLL(_name, _id, _parent, _conf) \
DEF_TYPE(_name, _id, CLK_TYPE_SAM_PLL, .parent = _parent, .conf = _conf)
+#define DEF_G3L_PLL(_name, _id, _parent, _conf, _default_rate) \
+ DEF_TYPE(_name, _id, CLK_TYPE_G3L_PLL, .parent = _parent, .conf = _conf, \
+ .default_rate = _default_rate)
#define DEF_G3S_PLL(_name, _id, _parent, _conf, _default_rate) \
DEF_TYPE(_name, _id, CLK_TYPE_G3S_PLL, .parent = _parent, .conf = _conf, \
.default_rate = _default_rate)
--
2.43.0
Powered by blists - more mailing lists