From d5d5da121b5024e87d3feaf8fb4dabc5c11cacd1 Mon Sep 17 00:00:00 2001 From: weijinmei Date: Mon, 14 Apr 2025 19:33:25 +0800 Subject: [PATCH] ccu: fix mux clk update childs by old freq when clk_set_rate Change-Id: Ifebf947d73f25aaa74f700b7fe59506cf525b9ea --- drivers/clk/spacemit/ccu-spacemit-k1x.c | 1 - drivers/clk/spacemit/ccu-spacemit-k1x.h | 1 + drivers/clk/spacemit/ccu_ddn.h | 6 ++++-- drivers/clk/spacemit/ccu_mix.c | 18 ++++++++++++++---- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/clk/spacemit/ccu-spacemit-k1x.c b/drivers/clk/spacemit/ccu-spacemit-k1x.c index 1c099cd8eaec..f5b8ba7026f2 100644 --- a/drivers/clk/spacemit/ccu-spacemit-k1x.c +++ b/drivers/clk/spacemit/ccu-spacemit-k1x.c @@ -1640,7 +1640,6 @@ void spacemit_clocks_init_rate(struct clk_hw_table *tbl, int tbl_size) clk = clk_hw_get_clk(spacemit_k1x_hw_clks.hws[tbl[i].clk_hw_id], tbl[i].name); if (!IS_ERR_OR_NULL(clk)) { clk_set_rate(clk, tbl[i].rate); - clk_get_rate(clk); } else pr_err("%s : can't find clk %s\n", __func__, tbl[i].name); diff --git a/drivers/clk/spacemit/ccu-spacemit-k1x.h b/drivers/clk/spacemit/ccu-spacemit-k1x.h index 7de56272b89a..bb18ebf923a5 100644 --- a/drivers/clk/spacemit/ccu-spacemit-k1x.h +++ b/drivers/clk/spacemit/ccu-spacemit-k1x.h @@ -50,6 +50,7 @@ struct ccu_common { unsigned long flags; spinlock_t *lock; struct clk_hw hw; + unsigned long rate; }; struct spacemit_k1x_clk { diff --git a/drivers/clk/spacemit/ccu_ddn.h b/drivers/clk/spacemit/ccu_ddn.h index b2a0ccc73b90..44fddfc52a71 100644 --- a/drivers/clk/spacemit/ccu_ddn.h +++ b/drivers/clk/spacemit/ccu_ddn.h @@ -58,7 +58,8 @@ struct ccu_ddn { .ddn = _SPACEMIT_CCU_DDN_CONFIG(_info, _table, _size), \ .common = { \ .reg_ctrl = _reg_ctrl, \ - .base_type = _base_type, \ + .base_type = _base_type, \ + .name = _name, \ .hw.init = CLK_HW_INIT(_name, \ _parent, \ &ccu_ddn_ops, \ @@ -75,7 +76,8 @@ struct ccu_ddn { .common = { \ .reg_ctrl = _reg_ddn, \ .reg_sel = __reg_gate, \ - .base_type = _base_type, \ + .base_type = _base_type, \ + .name = _name, \ .hw.init = CLK_HW_INIT(_name, \ _parent, \ &ccu_ddn_ops, \ diff --git a/drivers/clk/spacemit/ccu_mix.c b/drivers/clk/spacemit/ccu_mix.c index 296e147b1982..36791a52e99d 100644 --- a/drivers/clk/spacemit/ccu_mix.c +++ b/drivers/clk/spacemit/ccu_mix.c @@ -194,16 +194,22 @@ static unsigned long ccu_mix_recalc_rate(struct clk_hw *hw, struct ccu_mix *mix = hw_to_ccu_mix(hw); struct ccu_common * common = &mix->common; struct ccu_div_config *div = mix->div; + struct ccu_mux_config *mux = mix->mux ? mix->mux : NULL; unsigned long val; u32 reg; - if (!div){ + if (!div) { + if (mux && common->rate && common->rate != parent_rate) + parent_rate = common->rate; + if (mix->factor) - return parent_rate * mix->factor->mul / mix->factor->div; + val = parent_rate * mix->factor->mul / mix->factor->div; else - return parent_rate; + val = parent_rate; + + goto end; } - if (common->reg_type == CLK_DIV_TYPE_2REG_NOFC_V3 + if (common->reg_type == CLK_DIV_TYPE_2REG_NOFC_V3 || common->reg_type == CLK_DIV_TYPE_2REG_FC_V4) reg = readl(common->base + common->reg_sel); else @@ -215,6 +221,8 @@ static unsigned long ccu_mix_recalc_rate(struct clk_hw *hw, val = divider_recalc_rate(hw, parent_rate, val, div->table, div->flags, div->width); +end: + common->rate = val; return val; } @@ -338,6 +346,8 @@ static int ccu_mix_set_rate(struct clk_hw *hw, unsigned long rate, } best_rate = ccu_mix_calc_best_rate(hw, rate, &mux_val, &div_val); + common->rate = best_rate; + if (!strcmp(common->name, tswi8_clk_name)){ if(mux){ cur_mux = twsi8_reg_val >> mux->shift;