]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
clk: renesas: rzv2h: Skip monitor checks for external clocks
authorLad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Fri, 9 May 2025 16:01:20 +0000 (17:01 +0100)
committerGeert Uytterhoeven <geert+renesas@glider.be>
Tue, 10 Jun 2025 08:20:45 +0000 (10:20 +0200)
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>
drivers/clk/renesas/rzv2h-cpg.c
drivers/clk/renesas/rzv2h-cpg.h

index bcc496e8cbcda3d0c640c2400f2ebb849a280f62..2f045acc50802761b0eedba3db1273d3abc7f66d 100644 (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;
index 9104b1cd276c902761d9f8851c41277a84e0db4c..68c223373916cfba0e645ccfaeda27edc4b2b441 100644 (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