[PATCH v2 3/5] clk: mxl: Avoid disabling gate clocks from clk driver

From: Rahul Tanwar
Date: Mon Sep 05 2022 - 03:55:15 EST


In MxL's LGM SoC, gate clocks are supposed to be enabled or disabled
from EPU (power management IP) in certain power saving modes. If gate
clocks are allowed to be enabled/disabled from CGU clk driver, then
there arises a conflict where in case clk driver disables a gate clk,
and then EPU tries to disable the same gate clk, then it will hang
polling for the clk gated successful status.

To avoid such a conflict, disable gate clocks enabling/disabling from
CGU clk driver. But add a GATE_CLK_HW flag to control this in order to
be backward compatible with other SoCs which share the same CGU IP but
not the same EPU IP.

Signed-off-by: Rahul Tanwar <rtanwar@xxxxxxxxxxxxx>
---
drivers/clk/x86/clk-cgu.c | 32 ++++++++++++++++++++++++--------
drivers/clk/x86/clk-cgu.h | 1 +
2 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/x86/clk-cgu.c b/drivers/clk/x86/clk-cgu.c
index 1f7e93de67bc..d24173cfe0b0 100644
--- a/drivers/clk/x86/clk-cgu.c
+++ b/drivers/clk/x86/clk-cgu.c
@@ -258,8 +258,12 @@ static int lgm_clk_gate_enable(struct clk_hw *hw)
struct lgm_clk_gate *gate = to_lgm_clk_gate(hw);
unsigned int reg;

- reg = GATE_HW_REG_EN(gate->reg);
- lgm_set_clk_val(gate->membase, reg, gate->shift, 1, 1);
+ if (gate->flags & GATE_CLK_HW) {
+ reg = GATE_HW_REG_EN(gate->reg);
+ lgm_set_clk_val(gate->membase, reg, gate->shift, 1, 1);
+ } else {
+ gate->reg = 1;
+ }

return 0;
}
@@ -269,8 +273,12 @@ static void lgm_clk_gate_disable(struct clk_hw *hw)
struct lgm_clk_gate *gate = to_lgm_clk_gate(hw);
unsigned int reg;

- reg = GATE_HW_REG_DIS(gate->reg);
- lgm_set_clk_val(gate->membase, reg, gate->shift, 1, 1);
+ if (gate->flags & GATE_CLK_HW) {
+ reg = GATE_HW_REG_DIS(gate->reg);
+ lgm_set_clk_val(gate->membase, reg, gate->shift, 1, 1);
+ } else {
+ gate->reg = 0;
+ }
}

static int lgm_clk_gate_is_enabled(struct clk_hw *hw)
@@ -278,8 +286,12 @@ static int lgm_clk_gate_is_enabled(struct clk_hw *hw)
struct lgm_clk_gate *gate = to_lgm_clk_gate(hw);
unsigned int reg, ret;

- reg = GATE_HW_REG_STAT(gate->reg);
- ret = lgm_get_clk_val(gate->membase, reg, gate->shift, 1);
+ if (gate->flags & GATE_CLK_HW) {
+ reg = GATE_HW_REG_STAT(gate->reg);
+ ret = lgm_get_clk_val(gate->membase, reg, gate->shift, 1);
+ } else {
+ ret = gate->reg;
+ }

return ret;
}
@@ -315,7 +327,8 @@ lgm_clk_register_gate(struct lgm_clk_provider *ctx,
init.num_parents = pname ? 1 : 0;

gate->membase = ctx->membase;
- gate->reg = reg;
+ if (cflags & GATE_CLK_HW)
+ gate->reg = reg;
gate->shift = shift;
gate->flags = cflags;
gate->hw.init = &init;
@@ -326,7 +339,10 @@ lgm_clk_register_gate(struct lgm_clk_provider *ctx,
return ERR_PTR(ret);

if (cflags & CLOCK_FLAG_VAL_INIT) {
- lgm_set_clk_val(gate->membase, reg, shift, 1, list->gate_val);
+ if (cflags & GATE_CLK_HW)
+ lgm_set_clk_val(gate->membase, reg, shift, 1, list->gate_val);
+ else
+ gate->reg = 1;
}

return hw;
diff --git a/drivers/clk/x86/clk-cgu.h b/drivers/clk/x86/clk-cgu.h
index 0aa0f35d63a0..73ce84345f81 100644
--- a/drivers/clk/x86/clk-cgu.h
+++ b/drivers/clk/x86/clk-cgu.h
@@ -197,6 +197,7 @@ struct lgm_clk_branch {
/* clock flags definition */
#define CLOCK_FLAG_VAL_INIT BIT(16)
#define MUX_CLK_SW BIT(17)
+#define GATE_CLK_HW BIT(18)

#define LGM_MUX(_id, _name, _pdata, _f, _reg, \
_shift, _width, _cf, _v) \
--
2.17.1