clk: renesas: rzv2h: Skip monitor checks for external clocks

For module clocks whose parent mux may select an external source, bypass
the normal monitor (CLK_MON) register check when the external clock is
active. Introduce a new `ext_clk_mux_index` in `struct rzv2h_mod_clk` and
`struct mod_clock`, and detect the current mux index in
`rzv2h_mod_clock_is_enabled()` to disable monitoring if it matches the
external source index.

Provide the `DEF_MOD_MUX_EXTERNAL()` macro for declaring external-source
module clocks, and populate the `ext_clk_mux_index` field in
`rzv2h_cpg_register_mod_clk()`.

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/20250509160121.331073-2-prabhakar.mahadev-lad.rj@bp.renesas.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
pull/1279/head
Lad Prabhakar 2025-05-09 17:01:20 +01:00 committed by Geert Uytterhoeven
parent 19272b37aa
commit 899e7ede4c
2 changed files with 41 additions and 6 deletions

View File

@ -119,6 +119,7 @@ struct pll_clk {
* @on_bit: ON/MON bit
* @mon_index: monitor register offset
* @mon_bit: monitor bit
* @ext_clk_mux_index: mux index for external clock source, or -1 if internal
*/
struct mod_clock {
struct rzv2h_cpg_priv *priv;
@ -129,6 +130,7 @@ struct mod_clock {
u8 on_bit;
s8 mon_index;
u8 mon_bit;
s8 ext_clk_mux_index;
};
#define to_mod_clock(_hw) container_of(_hw, struct mod_clock, hw)
@ -563,15 +565,38 @@ static void rzv2h_mod_clock_mstop_disable(struct rzv2h_cpg_priv *priv,
spin_unlock_irqrestore(&priv->rmw_lock, flags);
}
static int rzv2h_parent_clk_mux_to_index(struct clk_hw *hw)
{
struct clk_hw *parent_hw;
struct clk *parent_clk;
struct clk_mux *mux;
u32 val;
/* This will always succeed, so no need to check for IS_ERR() */
parent_clk = clk_get_parent(hw->clk);
parent_hw = __clk_get_hw(parent_clk);
mux = to_clk_mux(parent_hw);
val = readl(mux->reg) >> mux->shift;
val &= mux->mask;
return clk_mux_val_to_index(parent_hw, mux->table, 0, val);
}
static int rzv2h_mod_clock_is_enabled(struct clk_hw *hw)
{
struct mod_clock *clock = to_mod_clock(hw);
struct rzv2h_cpg_priv *priv = clock->priv;
int mon_index = clock->mon_index;
u32 bitmask;
u32 offset;
if (clock->mon_index >= 0) {
offset = GET_CLK_MON_OFFSET(clock->mon_index);
if (clock->ext_clk_mux_index >= 0 &&
rzv2h_parent_clk_mux_to_index(hw) == clock->ext_clk_mux_index)
mon_index = -1;
if (mon_index >= 0) {
offset = GET_CLK_MON_OFFSET(mon_index);
bitmask = BIT(clock->mon_bit);
if (!(readl(priv->base + offset) & bitmask))
@ -687,6 +712,7 @@ rzv2h_cpg_register_mod_clk(const struct rzv2h_mod_clk *mod,
clock->mon_index = mod->mon_index;
clock->mon_bit = mod->mon_bit;
clock->no_pm = mod->no_pm;
clock->ext_clk_mux_index = mod->ext_clk_mux_index;
clock->priv = priv;
clock->hw.init = &init;
clock->mstop_data = mod->mstop_data;

View File

@ -199,6 +199,7 @@ enum clk_types {
* @on_bit: ON bit
* @mon_index: monitor register index
* @mon_bit: monitor bit
* @ext_clk_mux_index: mux index for external clock source, or -1 if internal
*/
struct rzv2h_mod_clk {
const char *name;
@ -210,9 +211,11 @@ struct rzv2h_mod_clk {
u8 on_bit;
s8 mon_index;
u8 mon_bit;
s8 ext_clk_mux_index;
};
#define DEF_MOD_BASE(_name, _mstop, _parent, _critical, _no_pm, _onindex, _onbit, _monindex, _monbit) \
#define DEF_MOD_BASE(_name, _mstop, _parent, _critical, _no_pm, _onindex, \
_onbit, _monindex, _monbit, _ext_clk_mux_index) \
{ \
.name = (_name), \
.mstop_data = (_mstop), \
@ -223,16 +226,22 @@ struct rzv2h_mod_clk {
.on_bit = (_onbit), \
.mon_index = (_monindex), \
.mon_bit = (_monbit), \
.ext_clk_mux_index = (_ext_clk_mux_index), \
}
#define DEF_MOD(_name, _parent, _onindex, _onbit, _monindex, _monbit, _mstop) \
DEF_MOD_BASE(_name, _mstop, _parent, false, false, _onindex, _onbit, _monindex, _monbit)
DEF_MOD_BASE(_name, _mstop, _parent, false, false, _onindex, _onbit, _monindex, _monbit, -1)
#define DEF_MOD_CRITICAL(_name, _parent, _onindex, _onbit, _monindex, _monbit, _mstop) \
DEF_MOD_BASE(_name, _mstop, _parent, true, false, _onindex, _onbit, _monindex, _monbit)
DEF_MOD_BASE(_name, _mstop, _parent, true, false, _onindex, _onbit, _monindex, _monbit, -1)
#define DEF_MOD_NO_PM(_name, _parent, _onindex, _onbit, _monindex, _monbit, _mstop) \
DEF_MOD_BASE(_name, _mstop, _parent, false, true, _onindex, _onbit, _monindex, _monbit)
DEF_MOD_BASE(_name, _mstop, _parent, false, true, _onindex, _onbit, _monindex, _monbit, -1)
#define DEF_MOD_MUX_EXTERNAL(_name, _parent, _onindex, _onbit, _monindex, _monbit, _mstop, \
_ext_clk_mux_index) \
DEF_MOD_BASE(_name, _mstop, _parent, false, false, _onindex, _onbit, _monindex, _monbit, \
_ext_clk_mux_index)
/**
* struct rzv2h_reset - Reset definitions