mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-02-19 21:50:17 -05:00
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 <prabhakar.mahadev-lad.rj@bp.renesas.com> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> Link: https://lore.kernel.org/20250627204237.214635-5-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
This commit is contained in:
committed by
Geert Uytterhoeven
parent
7aada0abe9
commit
87239caea4
@@ -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;
|
||||
|
||||
@@ -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, \
|
||||
|
||||
Reference in New Issue
Block a user