Commit 87239cae authored by Lad Prabhakar's avatar Lad Prabhakar Committed by Geert Uytterhoeven
Browse files

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: default avatarLad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/20250627204237.214635-5-prabhakar.mahadev-lad.rj@bp.renesas.com


Signed-off-by: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
parent 7aada0ab
Loading
Loading
Loading
Loading
+92 −0
Original line number Diff line number Diff line
@@ -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;
+22 −0
Original line number Diff line number Diff line
@@ -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, \