From: Lad Prabhakar Date: Fri, 27 Jun 2025 20:42:35 +0000 (+0100) Subject: clk: renesas: rzv2h: Add fixed-factor module clocks with status reporting X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=87239caea4dfbe69b34ddb6dd35fc58f2d395257;p=thirdparty%2Flinux.git clk: renesas: rzv2h: Add fixed-factor module clocks with status reporting Add support for fixed-factor module clocks that can report their enable status through the module status monitor. Introduce a new clock type, CLK_TYPE_FF_MOD_STATUS, and define the associated structure, rzv2h_ff_mod_status_clk, to manage these clocks. Implement the .is_enabled callback by reading the module status register using monitor index and bit definitions. Provide a helper macro, DEF_FIXED_MOD_STATUS, to simplify the definition of such clocks. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/20250627204237.214635-5-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- diff --git a/drivers/clk/renesas/rzv2h-cpg.c b/drivers/clk/renesas/rzv2h-cpg.c index 80a4484745645..f468afbb54e2d 100644 --- a/drivers/clk/renesas/rzv2h-cpg.c +++ b/drivers/clk/renesas/rzv2h-cpg.c @@ -77,6 +77,7 @@ * @resets: Array of resets * @num_resets: Number of Module Resets in info->resets[] * @last_dt_core_clk: ID of the last Core Clock exported to DT + * @ff_mod_status_ops: Fixed Factor Module Status Clock operations * @mstop_count: Array of mstop values * @rcdev: Reset controller entity */ @@ -92,6 +93,8 @@ struct rzv2h_cpg_priv { unsigned int num_resets; unsigned int last_dt_core_clk; + struct clk_ops *ff_mod_status_ops; + atomic_t *mstop_count; struct reset_controller_dev rcdev; @@ -149,6 +152,22 @@ struct ddiv_clk { #define to_ddiv_clock(_div) container_of(_div, struct ddiv_clk, div) +/** + * struct rzv2h_ff_mod_status_clk - Fixed Factor Module Status Clock + * + * @priv: CPG private data + * @conf: fixed mod configuration + * @fix: fixed factor clock + */ +struct rzv2h_ff_mod_status_clk { + struct rzv2h_cpg_priv *priv; + struct fixed_mod_conf conf; + struct clk_fixed_factor fix; +}; + +#define to_rzv2h_ff_mod_status_clk(_hw) \ + container_of(_hw, struct rzv2h_ff_mod_status_clk, fix.hw) + static int rzv2h_cpg_pll_clk_is_enabled(struct clk_hw *hw) { struct pll_clk *pll_clk = to_pll(hw); @@ -418,6 +437,65 @@ rzv2h_cpg_mux_clk_register(const struct cpg_core_clk *core, return clk_hw->clk; } +static int +rzv2h_clk_ff_mod_status_is_enabled(struct clk_hw *hw) +{ + struct rzv2h_ff_mod_status_clk *fix = to_rzv2h_ff_mod_status_clk(hw); + struct rzv2h_cpg_priv *priv = fix->priv; + u32 offset = GET_CLK_MON_OFFSET(fix->conf.mon_index); + u32 bitmask = BIT(fix->conf.mon_bit); + u32 val; + + val = readl(priv->base + offset); + return !!(val & bitmask); +} + +static struct clk * __init +rzv2h_cpg_fixed_mod_status_clk_register(const struct cpg_core_clk *core, + struct rzv2h_cpg_priv *priv) +{ + struct rzv2h_ff_mod_status_clk *clk_hw_data; + struct clk_init_data init = { }; + struct clk_fixed_factor *fix; + const struct clk *parent; + const char *parent_name; + int ret; + + WARN_DEBUG(core->parent >= priv->num_core_clks); + parent = priv->clks[core->parent]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + + parent_name = __clk_get_name(parent); + parent = priv->clks[core->parent]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + + clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL); + if (!clk_hw_data) + return ERR_PTR(-ENOMEM); + + clk_hw_data->priv = priv; + clk_hw_data->conf = core->cfg.fixed_mod; + + init.name = core->name; + init.ops = priv->ff_mod_status_ops; + init.flags = CLK_SET_RATE_PARENT; + init.parent_names = &parent_name; + init.num_parents = 1; + + fix = &clk_hw_data->fix; + fix->hw.init = &init; + fix->mult = core->mult; + fix->div = core->div; + + ret = devm_clk_hw_register(priv->dev, &clk_hw_data->fix.hw); + if (ret) + return ERR_PTR(ret); + + return clk_hw_data->fix.hw.clk; +} + static struct clk *rzv2h_cpg_clk_src_twocell_get(struct of_phandle_args *clkspec, void *data) @@ -496,6 +574,20 @@ rzv2h_cpg_register_core_clk(const struct cpg_core_clk *core, else clk = clk_hw->clk; break; + case CLK_TYPE_FF_MOD_STATUS: + if (!priv->ff_mod_status_ops) { + priv->ff_mod_status_ops = + devm_kzalloc(dev, sizeof(*priv->ff_mod_status_ops), GFP_KERNEL); + if (!priv->ff_mod_status_ops) { + clk = ERR_PTR(-ENOMEM); + goto fail; + } + memcpy(priv->ff_mod_status_ops, &clk_fixed_factor_ops, + sizeof(const struct clk_ops)); + priv->ff_mod_status_ops->is_enabled = rzv2h_clk_ff_mod_status_is_enabled; + } + clk = rzv2h_cpg_fixed_mod_status_clk_register(core, priv); + break; case CLK_TYPE_PLL: clk = rzv2h_cpg_pll_clk_register(core, priv, &rzv2h_cpg_pll_ops); break; diff --git a/drivers/clk/renesas/rzv2h-cpg.h b/drivers/clk/renesas/rzv2h-cpg.h index 25e0a9e5761b6..ba4f0196643f3 100644 --- a/drivers/clk/renesas/rzv2h-cpg.h +++ b/drivers/clk/renesas/rzv2h-cpg.h @@ -94,6 +94,23 @@ struct smuxed { .width = (_width), \ }) +/** + * struct fixed_mod_conf - Structure for fixed module configuration + * + * @mon_index: monitor index + * @mon_bit: monitor bit + */ +struct fixed_mod_conf { + u8 mon_index; + u8 mon_bit; +}; + +#define FIXED_MOD_CONF_PACK(_index, _bit) \ + ((struct fixed_mod_conf){ \ + .mon_index = (_index), \ + .mon_bit = (_bit), \ + }) + #define CPG_SSEL0 (0x300) #define CPG_SSEL1 (0x304) #define CPG_CDDIV0 (0x400) @@ -152,6 +169,7 @@ struct cpg_core_clk { struct ddiv ddiv; struct pll pll; struct smuxed smux; + struct fixed_mod_conf fixed_mod; } cfg; const struct clk_div_table *dtable; const char * const *parent_names; @@ -164,6 +182,7 @@ enum clk_types { /* Generic */ CLK_TYPE_IN, /* External Clock Input */ CLK_TYPE_FF, /* Fixed Factor Clock */ + CLK_TYPE_FF_MOD_STATUS, /* Fixed Factor Clock which can report the status of module clock */ CLK_TYPE_PLL, CLK_TYPE_DDIV, /* Dynamic Switching Divider */ CLK_TYPE_SMUX, /* Static Mux */ @@ -179,6 +198,9 @@ enum clk_types { DEF_TYPE(_name, _id, CLK_TYPE_IN) #define DEF_FIXED(_name, _id, _parent, _mult, _div) \ DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult) +#define DEF_FIXED_MOD_STATUS(_name, _id, _parent, _mult, _div, _gate) \ + DEF_BASE(_name, _id, CLK_TYPE_FF_MOD_STATUS, _parent, .div = _div, \ + .mult = _mult, .cfg.fixed_mod = _gate) #define DEF_DDIV(_name, _id, _parent, _ddiv_packed, _dtable) \ DEF_TYPE(_name, _id, CLK_TYPE_DDIV, \ .cfg.ddiv = _ddiv_packed, \