mirror of
https://github.com/torvalds/linux.git
synced 2026-07-29 18:51:21 +02:00
clk: renesas: rzg2l: Add support for enabling PLLs
Add support for enabling PLL clocks in the RZ/G3L CPG driver to turn off some PLLs, if they are not in use (e.g. PLL6, PLL7). Introduce .is_enabled() and .enable() callbacks to handle PLL state transitions. With the .enable() callback, the 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@bp.renesas.com> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> Link: https://patch.msgid.link/20260326110648.29389-3-biju.das.jz@bp.renesas.com Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
This commit is contained in:
parent
79b5d6970b
commit
78db1faa6b
|
|
@ -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)
|
||||
|
|
@ -1175,6 +1182,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/standby 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)
|
||||
|
|
@ -1258,6 +1322,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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user