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 <chuan.liu@amlogic.com>
This commit is contained in:
Chuan Liu
2024-04-03 19:31:37 +08:00
committed by yao zhang1
parent d891aa0114
commit ae4943530e
5 changed files with 530 additions and 298 deletions
+467 -9
View File
@@ -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 <carlo@endlessm.com>");
+22 -2
View File
@@ -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 */
+36 -280
View File
@@ -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
};
+4 -7
View File
@@ -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)
@@ -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 */