From ae4943530ea2116c78cc1787d4e32fb3c3587a03 Mon Sep 17 00:00:00 2001 From: Chuan Liu Date: Wed, 3 Apr 2024 19:31:37 +0800 Subject: [PATCH] clk: s7d: Fix known issue [1/1] PD#SWPL-163050 Problem: 1 PLL driver adds rstn features 2 Add ACLKM clock 3 Adapts to pll_v4_ops Solution: Fixed Verify: s7d_bm209 Change-Id: Ide5199539d388d9ee415ecf65f3c162b2e4c881c Signed-off-by: Chuan Liu --- drivers/clk/meson/clk-pll.c | 476 +++++++++++++++++++++- drivers/clk/meson/clk-pll.h | 24 +- drivers/clk/meson/s7d.c | 316 ++------------ include/dt-bindings/clock/s7d-clkc.h | 11 +- include/dt-bindings/clock/s7d-scmi-clkc.h | 1 + 5 files changed, 530 insertions(+), 298 deletions(-) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index e4a3117ce..01af0194e 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -225,10 +225,6 @@ static unsigned int __pll_params_with_frac(unsigned long rate, else frac_max = (1 << (pll->frac.width - 2)); - /* Bail out if we are already over the requested rate */ - if (rate < parent_rate * m / n) - return 0; - if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate); else @@ -635,10 +631,14 @@ static int meson_clk_pll_enable(struct clk_hw *hw) return 0; /* Make sure the pll is in reset */ - meson_parm_write(clk->map, &pll->rst, 1); + if (pll->flags & CLK_MESON_PLL_RSTN) + meson_parm_write(clk->map, &pll->rst, 0); + else + meson_parm_write(clk->map, &pll->rst, 1); /* Enable the pll */ meson_parm_write(clk->map, &pll->en, 1); + /* * Make the PLL more stable, if not, * It will probably lock failed (GP0 PLL) @@ -648,7 +648,10 @@ static int meson_clk_pll_enable(struct clk_hw *hw) #endif /* Take the pll out reset */ - meson_parm_write(clk->map, &pll->rst, 0); + if (pll->flags & CLK_MESON_PLL_RSTN) + meson_parm_write(clk->map, &pll->rst, 1); + else + meson_parm_write(clk->map, &pll->rst, 0); if (meson_clk_pll_wait_lock(hw)) return -EIO; @@ -665,7 +668,10 @@ static void meson_clk_pll_disable(struct clk_hw *hw) return; /* Put the pll is in reset */ - meson_parm_write(clk->map, &pll->rst, 1); + if (pll->flags & CLK_MESON_PLL_RSTN) + meson_parm_write(clk->map, &pll->rst, 0); + else + meson_parm_write(clk->map, &pll->rst, 1); /* Disable the pll */ meson_parm_write(clk->map, &pll->en, 0); @@ -1036,13 +1042,465 @@ const struct clk_ops meson_clk_pll_v3_ops = { .disable = meson_clk_pll_disable }; EXPORT_SYMBOL_GPL(meson_clk_pll_v3_ops); -#endif + +static unsigned long meson_clk_pll_params_to_rate(struct meson_clk_pll_data *pll, + unsigned long prate, + u32 m, u32 n, u32 frac, u32 od) +{ + u64 vco_rate, frac_rate; + u32 frac_precision; + + if (pll->flags & CLK_MESON_PLL_POWER_OF_TWO) + n = (u32)BIT(n); + + if (unlikely(!n)) + return 0; + + if (pll->flags & CLK_MESON_PLL_FIXED_EN0P5) + prate = prate >> 1; + + prate = DIV_ROUND_UP_ULL(prate, n); + vco_rate = (u64)prate * m; + + if (frac) { + if (pll->flags & CLK_MESON_PLL_FIXED_FRAC_WEIGHT_PRECISION) + frac_precision = FIXED_FRAC_WEIGHT_PRECISION; + else + frac_precision = (u32)BIT(pll->frac.width); + + frac_rate = (u64)prate * frac; + vco_rate += DIV_ROUND_UP_ULL(frac_rate, frac_precision); + } + + return vco_rate >> od; +} + +static unsigned long meson_clk_pll_v4_recalc_rate(struct clk_hw *hw, unsigned long prate) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); + unsigned int m, n, frac, od; + + n = meson_parm_read(clk->map, &pll->n); + m = meson_parm_read(clk->map, &pll->m); + od = meson_parm_read(clk->map, &pll->od); + + if (MESON_PARM_APPLICABLE(&pll->frac)) + frac = meson_parm_read(clk->map, &pll->frac); + else + frac = 0; + + return meson_clk_pll_params_to_rate(pll, prate, m, n, frac, od); +} + +static unsigned int meson_clk_pll_v4_get_range_m(unsigned long long rate, + unsigned long parent_rate, + unsigned int n, + struct meson_clk_pll_data *pll) +{ + u64 val; + + if (pll->flags & CLK_MESON_PLL_POWER_OF_TWO) + val = rate << n; + else + val = rate * n; + if (__pll_round_closest_mult(pll)) + return DIV_ROUND_CLOSEST_ULL(val, parent_rate); + + return div_u64(val, parent_rate); +} + +static int meson_clk_pll_get_range_value(struct meson_clk_pll_data *pll, + unsigned long rate, + unsigned long prate, + unsigned int *m, + unsigned int *n, + unsigned int *od) +{ + u64 vco_rate; + u32 idx; + unsigned int t_m; + unsigned long now, best = 0; + unsigned long t_prate = prate; + u32 od_max = BIT(pll->od.width) - 1; + + /* limit od max value for hw limit */ + if (unlikely(!!pll->od_max)) + od_max = pll->od_max; + + if (pll->flags & CLK_MESON_PLL_FIXED_N) { + *n = pll->fixed_n; + } else { + if (pll->flags & CLK_MESON_PLL_POWER_OF_TWO) + *n = 0; + else + *n = 1; + } + + for (idx = 0; idx <= od_max; idx++) { + vco_rate = (u64)rate << idx; + if (pll->flags & CLK_MESON_PLL_FIXED_EN0P5) + t_prate = prate >> 1; + t_m = meson_clk_pll_v4_get_range_m(vco_rate, t_prate, *n, pll); + if (t_m > pll->range->max) + break; + if (t_m < pll->range->min) + continue; + + now = meson_clk_pll_params_to_rate(pll, prate, t_m, *n, 0, idx); + if (meson_clk_pll_is_better(rate, best, now, pll)) { + best = now; + *m = t_m; + *od = idx; + if (now == rate) + break; + } + } + + return 0; +} + +static int meson_clk_pll_get_table_value(struct meson_clk_pll_data *pll, + unsigned long rate, + unsigned long prate, + unsigned int *m, + unsigned int *n, + unsigned int *od) +{ + u32 idx; + unsigned int t_m, t_n, t_od; + unsigned long now, best = 0; + + for (idx = 0; pll->table[idx].m; idx++) { + t_m = pll->table[idx].m; + t_n = pll->table[idx].n; + t_od = pll->table[idx].od; + + now = meson_clk_pll_params_to_rate(pll, prate, t_m, t_n, 0, t_od); + if (meson_clk_pll_is_better(rate, best, now, pll)) { + best = now; + *m = t_m; + *n = t_n; + *od = t_od; + if (now == rate) + break; + } + } + + return 0; +} + +static int meson_clk_pll_get_params_table(struct meson_clk_pll_data *pll, + unsigned long rate, + unsigned long prate, + unsigned int *m, + unsigned int *n, + unsigned int *od) +{ + if (pll->range) + return meson_clk_pll_get_range_value(pll, rate, prate, m, n, od); + else if (pll->table) + return meson_clk_pll_get_table_value(pll, rate, prate, m, n, od); + + return -EINVAL; +} + +static unsigned int meson_clk_pll_get_param_frac(struct meson_clk_pll_data *pll, + unsigned long rate, + unsigned long prate, + unsigned int m, + unsigned int n, + unsigned int od) +{ + unsigned int frac_max; + u64 vco_rate = (u64)rate << od; + u64 frac; + + if (pll->flags & CLK_MESON_PLL_FIXED_EN0P5) + prate = prate >> 1; + + if (pll->flags & CLK_MESON_PLL_POWER_OF_TWO) { + frac = vco_rate << n; + if (vco_rate < (((u64)prate >> n) * m)) + return 0; + } else { + frac = vco_rate * n; + /* Bail out if we are already over the requested rate */ + if (vco_rate < (div_u64((u64)prate * m, n))) + return 0; + } + if (pll->flags & CLK_MESON_PLL_FIXED_FRAC_WEIGHT_PRECISION) + frac_max = FIXED_FRAC_WEIGHT_PRECISION; + else + frac_max = 1 << pll->frac.width; + + if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) + frac = DIV_ROUND_CLOSEST_ULL(frac * frac_max, prate); + else + frac = div_u64(frac * frac_max, prate); + + frac -= (u64)m * frac_max; + return min_t(unsigned int, frac, frac_max); +} + +static int meson_clk_pll_v4_get_params(struct meson_clk_pll_data *pll, + unsigned long rate, + unsigned long prate, + unsigned int *best_m, + unsigned int *best_n, + unsigned int *best_od, + unsigned int *best_frac) +{ + int ret; + + ret = meson_clk_pll_get_params_table(pll, rate, prate, best_m, best_n, best_od); + if (ret) + return ret; + + if (MESON_PARM_APPLICABLE(&pll->frac)) + *best_frac = meson_clk_pll_get_param_frac(pll, rate, prate, + *best_m, *best_n, *best_od); + + return 0; +} + +static int meson_clk_pll_v4_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); + struct pll_rate_range *pll_range = &pll->pll_range; + unsigned long rate = req->rate; + + if (pll->flags & CLK_MESON_PLL_READ_ONLY) { + req->rate = clk_hw_get_rate(hw); + return 0; + } + + rate = clamp(rate, pll_range->min_rate, pll_range->max_rate); + rate = clamp(rate, req->min_rate, req->max_rate); + req->rate = rate; + + return 0; +} + +static bool meson_clk_pll_od_or_frac_correct(struct clk_regmap *clk, + struct meson_clk_pll_data *pll, + unsigned int m, unsigned int n) +{ + return meson_parm_read(clk->map, &pll->m) == m && + meson_parm_read(clk->map, &pll->n) == n && + meson_parm_read(clk->map, &pll->en); +} + +static int meson_clk_pll_v4_init(struct clk_hw *hw) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); + struct pll_rate_range *rate_range = &pll->pll_range; + + if (rate_range->max_rate == 0) + rate_range->max_rate = ULONG_MAX; + + //if (!pll->range && !pll->table) + // return -EINVAL; + /* + * Do not init pll + * 1. it will gate pll which is needed in RTOS + * 2. it will gate sys pll who is feeding CPU + */ + if (pll->flags & CLK_MESON_PLL_IGNORE_INIT) { + pr_warn("ignore %s clock init\n", clk_hw_get_name(hw)); + return 0; + } + + if (pll->init_count) { + if (pll->flags & CLK_MESON_PLL_RSTN) { + meson_parm_write(clk->map, &pll->rst, 0); + regmap_multi_reg_write(clk->map, pll->init_regs, + pll->init_count); + meson_parm_write(clk->map, &pll->rst, 1); + } else { + meson_parm_write(clk->map, &pll->rst, 1); + regmap_multi_reg_write(clk->map, pll->init_regs, + pll->init_count); + meson_parm_write(clk->map, &pll->rst, 0); + } + } + + return 0; +} + +static int meson_clk_pll_v4_enable(struct clk_hw *hw) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); + + /* do nothing if the PLL is already enabled */ + if (clk_hw_is_enabled(hw)) + return 0; + + /* Make sure the pll is in reset */ + if (pll->flags & CLK_MESON_PLL_RSTN) + meson_parm_write(clk->map, &pll->rst, 0); + else + meson_parm_write(clk->map, &pll->rst, 1); + + /* Enable the pll */ + meson_parm_write(clk->map, &pll->en, 1); + + /* Make sure the pll is in lock reset */ + if (MESON_PARM_APPLICABLE(&pll->l_rst)) { + if (pll->flags & CLK_MESON_PLL_RSTN) + meson_parm_write(clk->map, &pll->l_rst, 0); + else + meson_parm_write(clk->map, &pll->l_rst, 1); + } + + /* Make sure the pll force lock is clear */ + if (MESON_PARM_APPLICABLE(&pll->fl)) + meson_parm_write(clk->map, &pll->fl, 0); + + /* + * Make the PLL more stable, if not, + * It will probably lock failed (GP0 PLL) + */ + udelay(50); + + /* Take the pll out reset */ + if (pll->flags & CLK_MESON_PLL_RSTN) + meson_parm_write(clk->map, &pll->rst, 1); + else + meson_parm_write(clk->map, &pll->rst, 0); + + /* Take the pll out lock reset */ + if (MESON_PARM_APPLICABLE(&pll->l_rst)) { + udelay(20); + if (pll->flags & CLK_MESON_PLL_RSTN) + meson_parm_write(clk->map, &pll->l_rst, 1); + else + meson_parm_write(clk->map, &pll->l_rst, 0); + } + + if (meson_clk_pll_wait_lock(hw)) + return -EIO; + + /* Make sure the pll force lock is set */ + if (MESON_PARM_APPLICABLE(&pll->fl)) + meson_parm_write(clk->map, &pll->fl, 1); + + return 0; +} + +static void meson_clk_pll_v4_disable(struct clk_hw *hw) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); + + if (bypass_clk_disable) + return; + + /* Put the pll is in reset */ + if (pll->flags & CLK_MESON_PLL_RSTN) + meson_parm_write(clk->map, &pll->rst, 0); + else + meson_parm_write(clk->map, &pll->rst, 1); + + /* Disable the pll */ + meson_parm_write(clk->map, &pll->en, 0); +} + +static int meson_clk_pll_v4_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long prate) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); + unsigned int m, n, od, frac; + unsigned int enabled; + unsigned long old_rate, vco_rate; + int ret = 0; + + if (prate == 0 || rate == 0) + return -EINVAL; + + old_rate = clk_hw_get_rate(hw); + + /* calculate M, N, OD*/ + ret = meson_clk_pll_v4_get_params(pll, rate, prate, &m, &n, &od, &frac); + if (ret) + return ret; + + /* only frac correct, only write frac register only */ + if (meson_clk_pll_od_or_frac_correct(clk, pll, m, n)) { + if (unlikely(!!frac) && frac != meson_parm_read(clk->map, &pll->frac)) + /* Clear frac bits and Update frac value */ + meson_parm_write(clk->map, &pll->frac, frac); + if (unlikely(!!od) && od != meson_parm_read(clk->map, &pll->od)) + /* Clear od bits and Update od value */ + meson_parm_write(clk->map, &pll->od, od); + + return 0; + } + + enabled = meson_parm_read(clk->map, &pll->en); + if (enabled) + meson_clk_pll_v4_disable(hw); + + if (MESON_PARM_APPLICABLE(&pll->th)) { + vco_rate = meson_clk_pll_params_to_rate(pll, prate, m, n, frac, 0); + if (vco_rate >= MESON_PLL_THRESHOLD_RATE) + meson_parm_write(clk->map, &pll->th, 1); + else + meson_parm_write(clk->map, &pll->th, 0); + } + + meson_parm_write(clk->map, &pll->n, n); + meson_parm_write(clk->map, &pll->m, m); + meson_parm_write(clk->map, &pll->od, od); + if (MESON_PARM_APPLICABLE(&pll->frac)) + meson_parm_write(clk->map, &pll->frac, frac); + + /* If the pll is stopped, bail out now */ + if (!enabled) + return 0; + + ret = meson_clk_pll_v4_enable(hw); + if (ret) { + pr_warn("%s: pll did not lock, trying to restore old rate %lu\n", + __func__, old_rate); + /* + * FIXME: Do we really need/want this HACK ? + * It looks unsafe. what happens if the clock gets into a + * broken state and we can't lock back on the old_rate ? Looks + * like an infinite recursion is possible + */ + meson_clk_pll_v4_set_rate(hw, old_rate, prate); + } + + return ret; +} + +const struct clk_ops meson_clk_pll_v4_ops = { + /* walk the init regs each time when set a new rate, + * init callback is not useful for v3 ops + */ + .init = meson_clk_pll_v4_init, + .recalc_rate = meson_clk_pll_v4_recalc_rate, + .determine_rate = meson_clk_pll_v4_determine_rate, + .set_rate = meson_clk_pll_v4_set_rate, + .is_enabled = meson_clk_pll_is_enabled, + .enable = meson_clk_pll_v4_enable, + .disable = meson_clk_pll_v4_disable +}; +EXPORT_SYMBOL_GPL(meson_clk_pll_v4_ops); const struct clk_ops meson_clk_pll_ro_ops = { - .recalc_rate = meson_clk_pll_recalc_rate, + .init = meson_clk_pll_v4_init, + .recalc_rate = meson_clk_pll_v4_recalc_rate, .is_enabled = meson_clk_pll_is_enabled, }; EXPORT_SYMBOL_GPL(meson_clk_pll_ro_ops); +#endif MODULE_DESCRIPTION("Amlogic PLL driver"); MODULE_AUTHOR("Carlo Caione "); diff --git a/drivers/clk/meson/clk-pll.h b/drivers/clk/meson/clk-pll.h index 310a43f1e..55129730c 100644 --- a/drivers/clk/meson/clk-pll.h +++ b/drivers/clk/meson/clk-pll.h @@ -16,6 +16,11 @@ struct pll_mult_range { unsigned int max; }; +struct pll_rate_range { + unsigned long min_rate; + unsigned long max_rate; +}; + #if defined CONFIG_AMLOGIC_MODIFY && defined CONFIG_ARM struct pll_params_table { u16 m; @@ -35,6 +40,7 @@ struct pll_params_table { struct pll_params_table { unsigned int m; unsigned int n; + u16 od; const struct reg_sequence *regs; unsigned int regs_count; }; @@ -43,9 +49,17 @@ struct pll_params_table { { \ .m = (_m), \ .n = (_n), \ + .od = (0), \ } #endif +#define PLL_PARAMS_v4(_m, _n, _od) \ + { \ + .m = (_m), \ + .n = (_n), \ + .od = (_od), \ + } + #define CLK_MESON_PLL_ROUND_CLOSEST BIT(0) #define CLK_MESON_PLL_IGNORE_INIT BIT(1) #define CLK_MESON_PLL_FIXED_FRAC_WEIGHT_PRECISION BIT(2) @@ -54,10 +68,12 @@ struct pll_params_table { #define CLK_MESON_PLL_FIXED_EN0P5 BIT(5) /* * when PLL set the same rate, Do nothing in clk_set_rate, - * enable callback relock it, OD should not be cleared in ARM64, + * v3 enable callback relock it, OD should not be cleared in ARM64, * and retain it. */ #define CLK_MESON_PLL_RETAIN_OD BIT(6) +#define CLK_MESON_PLL_READ_ONLY BIT(7) +#define CLK_MESON_PLL_RSTN BIT(8) struct meson_clk_pll_data { struct parm en; @@ -66,6 +82,7 @@ struct meson_clk_pll_data { struct parm frac; struct parm l; struct parm rst; + struct parm l_rst; struct parm th; /* threshold */ struct parm fl; /* force lock */ /* for 32bit dco overflow */ @@ -77,8 +94,10 @@ struct meson_clk_pll_data { unsigned int init_count; const struct pll_params_table *table; const struct pll_mult_range *range; + struct pll_rate_range pll_range; + unsigned long od_max; unsigned int smc_id; - u8 flags; + u16 flags; u8 secid_disable; u8 secid; u8 fixed_n; @@ -89,5 +108,6 @@ extern const struct clk_ops meson_clk_pll_ops; extern const struct clk_ops meson_clk_pcie_pll_ops; extern const struct clk_ops meson_secure_pll_v2_ops; extern const struct clk_ops meson_clk_pll_v3_ops; +extern const struct clk_ops meson_clk_pll_v4_ops; #endif /* __MESON_CLK_PLL_H */ diff --git a/drivers/clk/meson/s7d.c b/drivers/clk/meson/s7d.c index 5613868e3..2a005cc23 100644 --- a/drivers/clk/meson/s7d.c +++ b/drivers/clk/meson/s7d.c @@ -273,13 +273,13 @@ static struct clk_fixed_factor _name = { \ }, \ } -#ifdef CONFIG_ARM #define __MESON_CLK_PLL(_name, _en_reg, _en_shift, _en_width, \ _m_reg, _m_shift, _m_width, \ _f_reg, _f_shift, _f_width, \ _n_reg, _n_shift, _n_width, \ _l_reg, _l_shift, _l_width, \ _r_reg, _r_shift, _r_width, \ + _l_rst_reg, _l_rst_shift, _l_rst_width, \ _init_reg, _init_reg_cnt, _range, _table, \ _smcid, _secid, _secid_dis, _dflags, \ _ops, _pname, _pdata, _phw, _iflags, \ @@ -292,6 +292,7 @@ static struct clk_regmap _name = { \ MEMBER_REG_PARM(n, _n_reg, _n_shift, _n_width), \ MEMBER_REG_PARM(l, _l_reg, _l_shift, _l_width), \ MEMBER_REG_PARM(rst, _r_reg, _r_shift, _r_width), \ + MEMBER_REG_PARM(l_rst, _l_rst_reg, _l_rst_shift, _l_rst_width),\ MEMBER_REG_PARM(od, _od_reg, _od_shift, _od_width), \ .range = _range, \ .table = _table, \ @@ -312,67 +313,6 @@ static struct clk_regmap _name = { \ .flags = _iflags, \ }, \ } -#else -#define __MESON_CLK_PLL(_name, _en_reg, _en_shift, _en_width, \ - _m_reg, _m_shift, _m_width, \ - _f_reg, _f_shift, _f_width, \ - _n_reg, _n_shift, _n_width, \ - _l_reg, _l_shift, _l_width, \ - _r_reg, _r_shift, _r_width, \ - _init_reg, _init_reg_cnt, _range, _table, \ - _smcid, _secid, _secid_dis, _dflags, \ - _ops, _pname, _pdata, _phw, _iflags, \ - _od_name, _od_reg, _od_shift, _od_width, \ - _od_table, _od_smcid, _od_secid, _od_dflags, \ - _od_ops, _od_iflags) \ -static struct clk_regmap _name = { \ - .data = &(struct meson_clk_pll_data){ \ - MEMBER_REG_PARM(en, _en_reg, _en_shift, _en_width), \ - MEMBER_REG_PARM(m, _m_reg, _m_shift, _m_width), \ - MEMBER_REG_PARM(frac, _f_reg, _f_shift, _f_width), \ - MEMBER_REG_PARM(n, _n_reg, _n_shift, _n_width), \ - MEMBER_REG_PARM(l, _l_reg, _l_shift, _l_width), \ - MEMBER_REG_PARM(rst, _r_reg, _r_shift, _r_width), \ - MEMBER_REG_PARM(od, _od_reg, _od_shift, _od_width), \ - .range = _range, \ - .table = _table, \ - .init_regs = _init_reg, \ - .init_count = _init_reg_cnt, \ - .smc_id = _smcid, \ - .secid = _secid, \ - .secid_disable = _secid_dis, \ - .flags = _dflags, \ - }, \ - .hw.init = &(struct clk_init_data){ \ - .name = # _name, \ - .ops = _ops, \ - .parent_names = _pname, \ - .parent_data = _pdata, \ - .parent_hws = _phw, \ - .num_parents = 1, \ - .flags = _iflags, \ - }, \ -}; \ -static struct clk_regmap _od_name = { \ - .data = &(struct clk_regmap_div_data){ \ - .offset = _od_reg, \ - .shift = _od_shift, \ - .width = _od_width, \ - .table = _od_table, \ - .smc_id = _od_smcid, \ - .secid = _od_secid, \ - .flags = _od_dflags, \ - }, \ - .hw.init = &(struct clk_init_data){ \ - .name = # _od_name, \ - .ops = _od_ops, \ - .parent_hws = (const struct clk_hw *[]) { \ - &_name.hw }, \ - .num_parents = 1, \ - .flags = _od_iflags, \ - }, \ -} -#endif #define MESON_CLK_MUX_RW(_name, _reg, _mask, _shift, _table, _dflags, \ _pdata, _iflags) \ @@ -456,13 +396,13 @@ static struct clk_regmap _od_name = { \ &meson_clk_dualdiv_ops, NULL, NULL, \ (const struct clk_hw *[]) { _phw }, _iflags) -#ifdef CONFIG_ARM #define MESON_CLK_PLL_RW(_name, _en_reg, _en_shift, _en_width, \ _m_reg, _m_shift, _m_width, \ _f_reg, _f_shift, _f_width, \ _n_reg, _n_shift, _n_width, \ _l_reg, _l_shift, _l_width, \ _r_reg, _r_shift, _r_width, \ + _l_rst_reg, _l_rst_shift, _l_rst_width, \ _init_reg, _range, _table, \ _dflags, _pdata, _iflags, \ _od_reg, _od_shift, _od_width) \ @@ -472,125 +412,12 @@ static struct clk_regmap _od_name = { \ _n_reg, _n_shift, _n_width, \ _l_reg, _l_shift, _l_width, \ _r_reg, _r_shift, _r_width, \ + _l_rst_reg, _l_rst_shift, _l_rst_width, \ _init_reg, ARRAY_SIZE(_init_reg), _range, _table,\ - 0, 0, 0, _dflags, &meson_clk_pll_v3_ops, \ + 0, 0, 0, _dflags, &meson_clk_pll_v4_ops, \ NULL, _pdata, NULL, _iflags, \ _od_reg, _od_shift, _od_width) -#define MESON_CLK_PLL_RO(_name, _en_reg, _en_shift, _en_width, \ - _m_reg, _m_shift, _m_width, \ - _f_reg, _f_shift, _f_width, \ - _n_reg, _n_shift, _n_width, \ - _l_reg, _l_shift, _l_width, \ - _r_reg, _r_shift, _r_width, \ - _dflags, _pdata, _iflags, \ - _od_reg, _od_shift, _od_width) \ - __MESON_CLK_PLL(_name, _en_reg, _en_shift, _en_width, \ - _m_reg, _m_shift, _m_width, \ - _f_reg, _f_shift, _f_width, \ - _n_reg, _n_shift, _n_width, \ - _l_reg, _l_shift, _l_width, \ - _r_reg, _r_shift, _r_width, \ - NULL, 0, NULL, NULL, \ - 0, 0, 0, _dflags, &meson_clk_pll_ro_ops, \ - NULL, _pdata, NULL, _iflags, \ - _od_reg, _od_shift, _od_width) - -#define MESON_CLK_PLL_SEC(_name, _en_reg, _en_shift, _en_width, \ - _m_reg, _m_shift, _m_width, \ - _f_reg, _f_shift, _f_width, \ - _n_reg, _n_shift, _n_width, \ - _l_reg, _l_shift, _l_width, \ - _r_reg, _r_shift, _r_width, \ - _range, _table, \ - _smcid, _secid, _secid_dis, _dflags, \ - _pdata, _iflags, \ - _od_reg, _od_shift, _od_width) \ - __MESON_CLK_PLL(_name, _en_reg, _en_shift, _en_width, \ - _m_reg, _m_shift, _m_width, \ - _f_reg, _f_shift, _f_width, \ - _n_reg, _n_shift, _n_width, \ - _l_reg, _l_shift, _l_width, \ - _r_reg, _r_shift, _r_width, \ - NULL, 0, _range, _table, \ - _smcid, _secid, _secid_dis, _dflags, \ - &meson_secure_pll_v2_ops, \ - NULL, _pdata, NULL, _iflags, \ - _od_reg, _od_shift, _od_width) -#else -#define MESON_CLK_PLL_RW(_name, _en_reg, _en_shift, _en_width, \ - _m_reg, _m_shift, _m_width, \ - _f_reg, _f_shift, _f_width, \ - _n_reg, _n_shift, _n_width, \ - _l_reg, _l_shift, _l_width, \ - _r_reg, _r_shift, _r_width, \ - _init_reg, _range, _table, \ - _dflags, _pdata, _iflags, \ - _od_reg, _od_shift, _od_width, _od_table, \ - _od_dflags) \ - __MESON_CLK_PLL(_name ## _dco, _en_reg, _en_shift, _en_width, \ - _m_reg, _m_shift, _m_width, \ - _f_reg, _f_shift, _f_width, \ - _n_reg, _n_shift, _n_width, \ - _l_reg, _l_shift, _l_width, \ - _r_reg, _r_shift, _r_width, \ - _init_reg, ARRAY_SIZE(_init_reg), _range, _table,\ - 0, 0, 0, _dflags, \ - &meson_clk_pll_v3_ops, \ - NULL, _pdata, NULL, _iflags, \ - _name, _od_reg, _od_shift, _od_width, \ - _od_table, 0, 0, _od_dflags, \ - &clk_regmap_divider_ops, CLK_SET_RATE_PARENT) - -#define MESON_CLK_PLL_RO(_name, _en_reg, _en_shift, _en_width, \ - _m_reg, _m_shift, _m_width, \ - _f_reg, _f_shift, _f_width, \ - _n_reg, _n_shift, _n_width, \ - _l_reg, _l_shift, _l_width, \ - _r_reg, _r_shift, _r_width, \ - _dflags, _pdata, _iflags, \ - _od_reg, _od_shift, _od_width, _od_table, \ - _od_dflags) \ - __MESON_CLK_PLL(_name ## _dco, _en_reg, _en_shift, _en_width, \ - _m_reg, _m_shift, _m_width, \ - _f_reg, _f_shift, _f_width, \ - _n_reg, _n_shift, _n_width, \ - _l_reg, _l_shift, _l_width, \ - _r_reg, _r_shift, _r_width, \ - NULL, 0, NULL, NULL, \ - 0, 0, 0, _dflags, \ - &meson_clk_pll_ro_ops, \ - NULL, _pdata, NULL, _iflags, \ - _name, _od_reg, _od_shift, _od_width, \ - _od_table, 0, 0, _od_dflags, \ - &clk_regmap_divider_ro_ops, CLK_SET_RATE_PARENT) - -#define MESON_CLK_PLL_SEC(_name, _en_reg, _en_shift, _en_width, \ - _m_reg, _m_shift, _m_width, \ - _f_reg, _f_shift, _f_width, \ - _n_reg, _n_shift, _n_width, \ - _l_reg, _l_shift, _l_width, \ - _r_reg, _r_shift, _r_width, \ - _range, _table, \ - _smcid, _secid, _secid_dis, _dflags, \ - _pdata, _iflags, \ - _od_reg, _od_shift, _od_width, _od_table, \ - _od_smcid, _od_secid, _od_dflags) \ - __MESON_CLK_PLL(_name ## _dco, _en_reg, _en_shift, _en_width, \ - _m_reg, _m_shift, _m_width, \ - _f_reg, _f_shift, _f_width, \ - _n_reg, _n_shift, _n_width, \ - _l_reg, _l_shift, _l_width, \ - _r_reg, _r_shift, _r_width, \ - NULL, 0, _range, _table, \ - _smcid, _secid, _secid_dis, _dflags, \ - &meson_secure_pll_v2_ops, \ - NULL, _pdata, NULL, _iflags, \ - _name, _od_reg, _od_shift, _od_width, \ - _od_table, _od_smcid, _od_secid, _od_dflags, \ - &clk_regmap_secure_v2_divider_ops, CLK_SET_RATE_PARENT) -#endif - #define __MESON_CLK_COMPOSITE(_m_name, _m_reg, _m_mask, _m_shift, \ _m_table, _m_dflags, _m_ops, _pname, \ _pdata, _phw, _pnub, _m_iflags, \ @@ -665,23 +492,6 @@ static struct clk_regmap _g_name = { \ _cname, _g_reg, _g_bit, _g_dflags, \ &clk_regmap_gate_ops, _g_iflags) -#define MESON_CLK_COMPOSITE_RO(_cname, _m_reg, _m_mask, _m_shift, \ - _m_table, _m_dflags, _m_pdata, _m_iflags,\ - _d_reg, _d_shift, _d_width, _d_table, \ - _d_dflags, _d_iflags, \ - _g_reg, _g_bit, _g_dflags, _g_iflags) \ - __MESON_CLK_COMPOSITE(_cname ## _sel, _m_reg, _m_mask, _m_shift,\ - _m_table, CLK_MUX_READ_ONLY | (_m_dflags),\ - &clk_regmap_mux_ro_ops, \ - NULL, _m_pdata, NULL, \ - ARRAY_SIZE(_m_pdata), _m_iflags, \ - _cname ## _div, \ - _d_reg, _d_shift, _d_width, _d_table, \ - CLK_DIVIDER_READ_ONLY | (_d_dflags), \ - &clk_regmap_divider_ro_ops, _d_iflags, \ - _cname, _g_reg, _g_bit, _g_dflags, \ - &clk_regmap_gate_ro_ops, _g_iflags) - static const struct clk_parent_data fclk_parent = { .fw_name = "fixed_pll", }; @@ -706,29 +516,18 @@ MESON_CLK_GATE_RO(fclk_div2p5, ANACTRL_FIXPLL_CTRL0, 25, 0, &fclk_div2p5_div.hw, MESON_CLK_FIXED_FACTOR_FCLK(fclk_clk50m_div, 1, 40); MESON_CLK_GATE_RO(fclk_clk50m, ANACTRL_FIXPLL_CTRL1, 31, 0, &fclk_clk50m_div.hw, 0); -#ifdef CONFIG_ARM static const struct pll_params_table gp0_pll_table[] = { - PLL_PARAMS(128, 0, 0), /* DCO = 1536M OD = 0 PLL = 1536M */ - PLL_PARAMS(192, 0, 1), /* DCO = 2304M OD = 1 PLL = 1152M */ + PLL_PARAMS_v4(128, 0, 0), /* DCO = 1536M OD = 0 PLL = 1536M */ + PLL_PARAMS_v4(192, 0, 1), /* DCO = 2304M OD = 1 PLL = 1152M */ { /* sentinel */ } }; -#else -static const struct pll_params_table gp0_pll_table[] = { - PLL_PARAMS(128, 0), /* DCO = 1536M */ - PLL_PARAMS(192, 0), /* DCO = 2304M */ - { /* sentinel */ } -}; -#endif static const struct reg_sequence gp0_init_regs[] = { - { .reg = ANACTRL_GP0PLL_CTRL0, .def = 0x000100ea }, - { .reg = ANACTRL_GP0PLL_CTRL1, .def = 0x1148cd00 }, + { .reg = ANACTRL_GP0PLL_CTRL0, .def = 0x00010000 }, + { .reg = ANACTRL_GP0PLL_CTRL1, .def = 0x11480000 }, { .reg = ANACTRL_GP0PLL_CTRL2, .def = 0x1219b010 }, - { .reg = ANACTRL_GP0PLL_CTRL3, .def = 0x00008010 }, - { .reg = ANACTRL_GP0PLL_CTRL4, .def = 0x1f01110f }, - { .reg = ANACTRL_GP0PLL_CTRL1, .def = 0x1948cd00, .delay_us = 20 }, - { .reg = ANACTRL_GP0PLL_CTRL0, .def = 0x200100ea, .delay_us = 20 }, { .reg = ANACTRL_GP0PLL_CTRL3, .def = 0x20008010 }, + { .reg = ANACTRL_GP0PLL_CTRL4, .def = 0x1f01110f } }; static const struct clk_parent_data gp0_pll_parent = { @@ -737,44 +536,30 @@ static const struct clk_parent_data gp0_pll_parent = { MESON_CLK_PLL_RW(gp0_pll, ANACTRL_GP0PLL_CTRL1, 27, 1, /* en */ ANACTRL_GP0PLL_CTRL0, 0, 9, /* m */ - ANACTRL_GP0PLL_CTRL1, 0, 19, /* frac */ + ANACTRL_GP0PLL_CTRL1, 0, 17, /* frac */ ANACTRL_GP0PLL_CTRL0, 12, 3, /* n */ ANACTRL_GP0PLL_CTRL0, 31, 1, /* lock */ ANACTRL_GP0PLL_CTRL0, 29, 1, /* rst */ + ANACTRL_GP0PLL_CTRL3, 29, 1, /* l_rst */ gp0_init_regs, NULL, gp0_pll_table, /* init_regs, range, table */ - CLK_MESON_PLL_POWER_OF_TWO | CLK_MESON_PLL_FIXED_EN0P5, /* dflags */ + CLK_MESON_PLL_POWER_OF_TWO | CLK_MESON_PLL_FIXED_EN0P5 | + CLK_MESON_PLL_IGNORE_INIT | CLK_MESON_PLL_RSTN, /* dflags */ &gp0_pll_parent, 0, /* pdata, iflags */ - ANACTRL_GP0PLL_CTRL0, 20, 3 /* od */ -#ifdef CONFIG_ARM - ); -#else - , NULL, CLK_DIVIDER_POWER_OF_TWO); /* od_table, od_dflags */ -#endif + ANACTRL_GP0PLL_CTRL0, 20, 3); /* od */ -#ifdef CONFIG_ARM static const struct pll_params_table hifi_pll_table[] = { - PLL_PARAMS(150, 0, 0), /* DCO = 1800M OD = 0 PLL = 1800M */ - PLL_PARAMS(150, 0, 2), /* DCO = 1800M OD = 4 PLL = 450M */ - PLL_PARAMS(163, 0, 2), /* DCO = 1944M OD = 4 PLL = 486M */ + PLL_PARAMS_v4(150, 0, 0), /* DCO = 1800M OD = 0 PLL = 1800M */ + PLL_PARAMS_v4(150, 0, 2), /* DCO = 1800M OD = 4 PLL = 450M */ + PLL_PARAMS_v4(163, 0, 2), /* DCO = 1944M OD = 4 PLL = 486M */ { /* sentinel */ } }; -#else -static const struct pll_params_table hifi_pll_table[] = { - PLL_PARAMS(150, 0), /* DCO = 1800M */ - PLL_PARAMS(163, 0), /* DCO = 1944M */ - { /* sentinel */ } -}; -#endif static const struct reg_sequence hifi0_init_regs[] = { - { .reg = ANACTRL_HIFI0PLL_CTRL0, .def = 0x000100ea }, - { .reg = ANACTRL_HIFI0PLL_CTRL1, .def = 0x11489c40 }, + { .reg = ANACTRL_HIFI0PLL_CTRL0, .def = 0x00010000 }, + { .reg = ANACTRL_HIFI0PLL_CTRL1, .def = 0x11480000 }, { .reg = ANACTRL_HIFI0PLL_CTRL2, .def = 0x1219b010 }, - { .reg = ANACTRL_HIFI0PLL_CTRL3, .def = 0x00008010 }, - { .reg = ANACTRL_HIFI0PLL_CTRL4, .def = 0x1f01110f }, - { .reg = ANACTRL_HIFI0PLL_CTRL1, .def = 0x19489c40, .delay_us = 20 }, - { .reg = ANACTRL_HIFI0PLL_CTRL0, .def = 0x200100ea, .delay_us = 20 }, - { .reg = ANACTRL_HIFI0PLL_CTRL3, .def = 0x20008010 } + { .reg = ANACTRL_HIFI0PLL_CTRL3, .def = 0x20008010 }, + { .reg = ANACTRL_HIFI0PLL_CTRL4, .def = 0x1f01110f } }; static const struct clk_parent_data hifi0_pll_parent = { @@ -783,31 +568,24 @@ static const struct clk_parent_data hifi0_pll_parent = { MESON_CLK_PLL_RW(hifi_pll, ANACTRL_HIFI0PLL_CTRL1, 27, 1, /* en */ ANACTRL_HIFI0PLL_CTRL0, 0, 9, /* m */ - ANACTRL_HIFI0PLL_CTRL1, 0, 19, /* frac */ + ANACTRL_HIFI0PLL_CTRL1, 0, 17, /* frac */ ANACTRL_HIFI0PLL_CTRL0, 12, 3, /* n */ ANACTRL_HIFI0PLL_CTRL0, 31, 1, /* lock */ ANACTRL_HIFI0PLL_CTRL0, 29, 1, /* rst */ + ANACTRL_HIFI0PLL_CTRL3, 29, 1, /* l_rst */ hifi0_init_regs, NULL, hifi_pll_table, /* init_regs, range, table */ CLK_MESON_PLL_POWER_OF_TWO | CLK_MESON_PLL_FIXED_EN0P5 | - CLK_MESON_PLL_FIXED_FRAC_WEIGHT_PRECISION, /* dflags */ + CLK_MESON_PLL_FIXED_FRAC_WEIGHT_PRECISION | + CLK_MESON_PLL_RSTN, /* dflags */ &hifi0_pll_parent, 0, /* pdata, iflags */ - ANACTRL_HIFI0PLL_CTRL0, 20, 3 /* od */ -#ifdef CONFIG_ARM - ); -#else - , NULL, /* od_table */ - CLK_DIVIDER_POWER_OF_TWO | CLK_DIVIDER_ROUND_CLOSEST); /* od_dflags */ -#endif + ANACTRL_HIFI0PLL_CTRL0, 20, 3); /* od */ static const struct reg_sequence hifi1_init_regs[] = { - { .reg = ANACTRL_HIFI1PLL_CTRL0, .def = 0x000100ea }, - { .reg = ANACTRL_HIFI1PLL_CTRL1, .def = 0x11489c40 }, + { .reg = ANACTRL_HIFI1PLL_CTRL0, .def = 0x00010000 }, + { .reg = ANACTRL_HIFI1PLL_CTRL1, .def = 0x11480000 }, { .reg = ANACTRL_HIFI1PLL_CTRL2, .def = 0x1219b010 }, - { .reg = ANACTRL_HIFI1PLL_CTRL3, .def = 0x00008010 }, - { .reg = ANACTRL_HIFI1PLL_CTRL4, .def = 0x1f01110f }, - { .reg = ANACTRL_HIFI1PLL_CTRL1, .def = 0x19489c40, .delay_us = 20 }, - { .reg = ANACTRL_HIFI1PLL_CTRL0, .def = 0x200100ea, .delay_us = 20 }, - { .reg = ANACTRL_HIFI1PLL_CTRL3, .def = 0x20008010 } + { .reg = ANACTRL_HIFI1PLL_CTRL3, .def = 0x20008010 }, + { .reg = ANACTRL_HIFI1PLL_CTRL4, .def = 0x1f01110f } }; static const struct clk_parent_data hifi1_pll_parent = { @@ -816,21 +594,17 @@ static const struct clk_parent_data hifi1_pll_parent = { MESON_CLK_PLL_RW(hifi1_pll, ANACTRL_HIFI1PLL_CTRL1, 27, 1, /* en */ ANACTRL_HIFI1PLL_CTRL0, 0, 9, /* m */ - ANACTRL_HIFI1PLL_CTRL1, 0, 19, /* frac */ + ANACTRL_HIFI1PLL_CTRL1, 0, 17, /* frac */ ANACTRL_HIFI1PLL_CTRL0, 12, 3, /* n */ ANACTRL_HIFI1PLL_CTRL0, 31, 1, /* lock */ ANACTRL_HIFI1PLL_CTRL0, 29, 1, /* rst */ + ANACTRL_HIFI1PLL_CTRL3, 29, 1, /* l_rst */ hifi1_init_regs, NULL, hifi_pll_table, /* init_regs, range, table */ CLK_MESON_PLL_POWER_OF_TWO | CLK_MESON_PLL_FIXED_EN0P5 | - CLK_MESON_PLL_FIXED_FRAC_WEIGHT_PRECISION, /* dflags */ + CLK_MESON_PLL_FIXED_FRAC_WEIGHT_PRECISION | + CLK_MESON_PLL_RSTN, /* dflags */ &hifi1_pll_parent, 0, /* pdata, iflags */ - ANACTRL_HIFI1PLL_CTRL0, 20, 3 /* od */ -#ifdef CONFIG_ARM - ); -#else - , NULL, /* od_table */ - CLK_DIVIDER_POWER_OF_TWO | CLK_DIVIDER_ROUND_CLOSEST); /* od_dflags */ -#endif + ANACTRL_HIFI1PLL_CTRL0, 20, 3); /* od */ static const struct clk_parent_data rtc_dual_clkin_parent = { .fw_name = "xtal", @@ -1747,17 +1521,8 @@ static struct clk_hw_onecell_data s7d_hw_onecell_data = { [CLKID_FCLK_CLK50M_DIV] = &fclk_clk50m_div.hw, [CLKID_FCLK_CLK50M] = &fclk_clk50m.hw, -#ifndef CONFIG_ARM - [CLKID_GP0_PLL_DCO] = &gp0_pll_dco.hw, -#endif [CLKID_GP0_PLL] = &gp0_pll.hw, -#ifndef CONFIG_ARM - [CLKID_HIFI_PLL_DCO] = &hifi_pll_dco.hw, -#endif [CLKID_HIFI_PLL] = &hifi_pll.hw, -#ifndef CONFIG_ARM - [CLKID_HIFI1_PLL_DCO] = &hifi1_pll_dco.hw, -#endif [CLKID_HIFI1_PLL] = &hifi1_pll.hw, [CLKID_RTC_DUAL_CLKIN] = &rtc_dual_clkin.hw, @@ -2317,17 +2082,8 @@ static struct clk_regmap *const s7d_pll_clk_regmaps[] = { &fclk_div7, &fclk_div2p5, &fclk_clk50m, -#ifndef CONFIG_ARM - &gp0_pll_dco, -#endif &gp0_pll, -#ifndef CONFIG_ARM - &hifi_pll_dco, -#endif &hifi_pll, -#ifndef CONFIG_ARM - &hifi1_pll_dco, -#endif &hifi1_pll }; diff --git a/include/dt-bindings/clock/s7d-clkc.h b/include/dt-bindings/clock/s7d-clkc.h index b16a67306..866bd31f2 100644 --- a/include/dt-bindings/clock/s7d-clkc.h +++ b/include/dt-bindings/clock/s7d-clkc.h @@ -24,14 +24,11 @@ #define CLKID_FCLK_DIV2P5 (CLKID_PLL_BASE + 11) #define CLKID_FCLK_CLK50M_DIV (CLKID_PLL_BASE + 12) #define CLKID_FCLK_CLK50M (CLKID_PLL_BASE + 13) -#define CLKID_GP0_PLL_DCO (CLKID_PLL_BASE + 14) -#define CLKID_GP0_PLL (CLKID_PLL_BASE + 15) -#define CLKID_HIFI_PLL_DCO (CLKID_PLL_BASE + 16) -#define CLKID_HIFI_PLL (CLKID_PLL_BASE + 17) -#define CLKID_HIFI1_PLL_DCO (CLKID_PLL_BASE + 18) -#define CLKID_HIFI1_PLL (CLKID_PLL_BASE + 19) +#define CLKID_GP0_PLL (CLKID_PLL_BASE + 14) +#define CLKID_HIFI_PLL (CLKID_PLL_BASE + 15) +#define CLKID_HIFI1_PLL (CLKID_PLL_BASE + 16) -#define CLKID_BASIC_BASE (CLKID_PLL_BASE + 20) +#define CLKID_BASIC_BASE (CLKID_PLL_BASE + 17) #define CLKID_RTC_DUAL_CLKIN (CLKID_BASIC_BASE + 0) #define CLKID_RTC_DUAL_DIV (CLKID_BASIC_BASE + 1) #define CLKID_RTC_DUAL_SEL (CLKID_BASIC_BASE + 2) diff --git a/include/dt-bindings/clock/s7d-scmi-clkc.h b/include/dt-bindings/clock/s7d-scmi-clkc.h index 9dfed7bb0..80ecfcc4c 100644 --- a/include/dt-bindings/clock/s7d-scmi-clkc.h +++ b/include/dt-bindings/clock/s7d-scmi-clkc.h @@ -27,6 +27,7 @@ #define CLKID_SCMI_DSU_CLK 15 #define CLKID_SCMI_FIXED_PLL 16 #define CLKID_SCMI_GP1_PLL 17 +#define CLKID_SCMI_ACLKM 18 #endif /* __S7D_CLKC_H */