},
};
-static const struct pll_rate_table axg_gp0_pll_rate_table[] = {
- PLL_RATE(960000000, 40, 1),
- PLL_RATE(984000000, 41, 1),
- PLL_RATE(1008000000, 42, 1),
- PLL_RATE(1032000000, 43, 1),
- PLL_RATE(1056000000, 44, 1),
- PLL_RATE(1080000000, 45, 1),
- PLL_RATE(1104000000, 46, 1),
- PLL_RATE(1128000000, 47, 1),
- PLL_RATE(1152000000, 48, 1),
- PLL_RATE(1176000000, 49, 1),
- PLL_RATE(1200000000, 50, 1),
- PLL_RATE(1224000000, 51, 1),
- PLL_RATE(1248000000, 52, 1),
- PLL_RATE(1272000000, 53, 1),
- PLL_RATE(1296000000, 54, 1),
- PLL_RATE(1320000000, 55, 1),
- PLL_RATE(1344000000, 56, 1),
- PLL_RATE(1368000000, 57, 1),
- PLL_RATE(1392000000, 58, 1),
- PLL_RATE(1416000000, 59, 1),
- PLL_RATE(1440000000, 60, 1),
- PLL_RATE(1464000000, 61, 1),
- PLL_RATE(1488000000, 62, 1),
- PLL_RATE(1512000000, 63, 1),
- PLL_RATE(1536000000, 64, 1),
- PLL_RATE(1560000000, 65, 1),
- PLL_RATE(1584000000, 66, 1),
- PLL_RATE(1608000000, 67, 1),
- PLL_RATE(1632000000, 68, 1),
+static const struct pll_params_table axg_gp0_pll_params_table[] = {
+ PLL_PARAMS(40, 1),
+ PLL_PARAMS(41, 1),
+ PLL_PARAMS(42, 1),
+ PLL_PARAMS(43, 1),
+ PLL_PARAMS(44, 1),
+ PLL_PARAMS(45, 1),
+ PLL_PARAMS(46, 1),
+ PLL_PARAMS(47, 1),
+ PLL_PARAMS(48, 1),
+ PLL_PARAMS(49, 1),
+ PLL_PARAMS(50, 1),
+ PLL_PARAMS(51, 1),
+ PLL_PARAMS(52, 1),
+ PLL_PARAMS(53, 1),
+ PLL_PARAMS(54, 1),
+ PLL_PARAMS(55, 1),
+ PLL_PARAMS(56, 1),
+ PLL_PARAMS(57, 1),
+ PLL_PARAMS(58, 1),
+ PLL_PARAMS(59, 1),
+ PLL_PARAMS(60, 1),
+ PLL_PARAMS(61, 1),
+ PLL_PARAMS(62, 1),
+ PLL_PARAMS(63, 1),
+ PLL_PARAMS(64, 1),
+ PLL_PARAMS(65, 1),
+ PLL_PARAMS(66, 1),
+ PLL_PARAMS(67, 1),
+ PLL_PARAMS(68, 1),
{ /* sentinel */ },
};
.shift = 29,
.width = 1,
},
- .table = axg_gp0_pll_rate_table,
+ .table = axg_gp0_pll_params_table,
.init_regs = axg_gp0_init_regs,
.init_count = ARRAY_SIZE(axg_gp0_init_regs),
},
.shift = 29,
.width = 1,
},
- .table = axg_gp0_pll_rate_table,
+ .table = axg_gp0_pll_params_table,
.init_regs = axg_hifi_init_regs,
.init_count = ARRAY_SIZE(axg_hifi_init_regs),
.flags = CLK_MESON_PLL_ROUND_CLOSEST,
},
};
-static const struct pll_rate_table axg_pcie_pll_rate_table[] = {
+static const struct pll_params_table axg_pcie_pll_params_table[] = {
{
- .rate = 1600000000,
- .m = 200,
- .n = 3,
+ .m = 200,
+ .n = 3,
},
{ /* sentinel */ },
};
.shift = 29,
.width = 1,
},
- .table = axg_pcie_pll_rate_table,
+ .table = axg_pcie_pll_params_table,
.init_regs = axg_pcie_init_regs,
.init_count = ARRAY_SIZE(axg_pcie_init_regs),
},
}
static unsigned long __pll_params_to_rate(unsigned long parent_rate,
- const struct pll_rate_table *pllt,
+ const struct pll_params_table *pllt,
u16 frac,
struct meson_clk_pll_data *pll)
{
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
- struct pll_rate_table pllt;
+ struct pll_params_table pllt;
u16 frac;
pllt.n = meson_parm_read(clk->map, &pll->n);
static u16 __pll_params_with_frac(unsigned long rate,
unsigned long parent_rate,
- const struct pll_rate_table *pllt,
+ const struct pll_params_table *pllt,
struct meson_clk_pll_data *pll)
{
u16 frac_max = (1 << pll->frac.width);
return min((u16)val, (u16)(frac_max - 1));
}
-static const struct pll_rate_table *
+static bool meson_clk_pll_is_better(unsigned long rate,
+ unsigned long best,
+ unsigned long now,
+ struct meson_clk_pll_data *pll)
+{
+ if (!(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
+ MESON_PARM_APPLICABLE(&pll->frac)) {
+ /* Round down */
+ if (now < rate && best < now)
+ return true;
+ } else {
+ /* Round Closest */
+ if (abs(now - rate) < abs(best - rate))
+ return true;
+ }
+
+ return false;
+}
+
+static const struct pll_params_table *
meson_clk_get_pll_settings(unsigned long rate,
+ unsigned long parent_rate,
struct meson_clk_pll_data *pll)
{
- const struct pll_rate_table *table = pll->table;
- unsigned int i = 0;
+ const struct pll_params_table *table = pll->table;
+ unsigned long best = 0, now = 0;
+ unsigned int i, best_i = 0;
if (!table)
return NULL;
- /* Find the first table element exceeding rate */
- while (table[i].rate && table[i].rate <= rate)
- i++;
+ for (i = 0; table[i].n; i++) {
+ now = __pll_params_to_rate(parent_rate, &table[i], 0, pll);
- if (i != 0) {
- if (MESON_PARM_APPLICABLE(&pll->frac) ||
- !(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
- (abs(rate - table[i - 1].rate) <
- abs(rate - table[i].rate)))
- i--;
+ /* If we get an exact match, don't bother any further */
+ if (now == rate) {
+ return &table[i];
+ } else if (meson_clk_pll_is_better(rate, best, now, pll)) {
+ best = now;
+ best_i = i;
+ }
}
- return (struct pll_rate_table *)&table[i];
+ return (struct pll_params_table *)&table[best_i];
}
static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
- const struct pll_rate_table *pllt =
- meson_clk_get_pll_settings(rate, pll);
+ const struct pll_params_table *pllt =
+ meson_clk_get_pll_settings(rate, *parent_rate, pll);
+ unsigned long round;
u16 frac;
if (!pllt)
return meson_clk_pll_recalc_rate(hw, *parent_rate);
- if (!MESON_PARM_APPLICABLE(&pll->frac)
- || rate == pllt->rate)
- return pllt->rate;
+ round = __pll_params_to_rate(*parent_rate, pllt, 0, pll);
+
+ if (!MESON_PARM_APPLICABLE(&pll->frac) || rate == round)
+ return round;
/*
* The rate provided by the setting is not an exact match, let's
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
- const struct pll_rate_table *pllt;
+ const struct pll_params_table *pllt;
unsigned int enabled;
unsigned long old_rate;
u16 frac = 0;
old_rate = rate;
- pllt = meson_clk_get_pll_settings(rate, pll);
+ pllt = meson_clk_get_pll_settings(rate, parent_rate, pll);
if (!pllt)
return -EINVAL;
}
-struct pll_rate_table {
- unsigned long rate;
+struct pll_params_table {
u16 m;
u16 n;
};
-#define PLL_RATE(_r, _m, _n) \
+#define PLL_PARAMS(_m, _n) \
{ \
- .rate = (_r), \
.m = (_m), \
.n = (_n), \
}
struct parm rst;
const struct reg_sequence *init_regs;
unsigned int init_count;
- const struct pll_rate_table *table;
+ const struct pll_params_table *table;
u8 flags;
};
static DEFINE_SPINLOCK(meson_clk_lock);
-static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = {
- PLL_RATE(768000000, 32, 1),
- PLL_RATE(792000000, 33, 1),
- PLL_RATE(816000000, 34, 1),
- PLL_RATE(840000000, 35, 1),
- PLL_RATE(864000000, 36, 1),
- PLL_RATE(888000000, 37, 1),
- PLL_RATE(912000000, 38, 1),
- PLL_RATE(936000000, 39, 1),
- PLL_RATE(960000000, 40, 1),
- PLL_RATE(984000000, 41, 1),
- PLL_RATE(1008000000, 42, 1),
- PLL_RATE(1032000000, 43, 1),
- PLL_RATE(1056000000, 44, 1),
- PLL_RATE(1080000000, 45, 1),
- PLL_RATE(1104000000, 46, 1),
- PLL_RATE(1128000000, 47, 1),
- PLL_RATE(1152000000, 48, 1),
- PLL_RATE(1176000000, 49, 1),
- PLL_RATE(1200000000, 50, 1),
- PLL_RATE(1224000000, 51, 1),
- PLL_RATE(1248000000, 52, 1),
- PLL_RATE(1272000000, 53, 1),
- PLL_RATE(1296000000, 54, 1),
- PLL_RATE(1320000000, 55, 1),
- PLL_RATE(1344000000, 56, 1),
- PLL_RATE(1368000000, 57, 1),
- PLL_RATE(1392000000, 58, 1),
- PLL_RATE(1416000000, 59, 1),
- PLL_RATE(1440000000, 60, 1),
- PLL_RATE(1464000000, 61, 1),
- PLL_RATE(1488000000, 62, 1),
+static const struct pll_params_table gxbb_gp0_pll_params_table[] = {
+ PLL_PARAMS(32, 1),
+ PLL_PARAMS(33, 1),
+ PLL_PARAMS(34, 1),
+ PLL_PARAMS(35, 1),
+ PLL_PARAMS(36, 1),
+ PLL_PARAMS(37, 1),
+ PLL_PARAMS(38, 1),
+ PLL_PARAMS(39, 1),
+ PLL_PARAMS(40, 1),
+ PLL_PARAMS(41, 1),
+ PLL_PARAMS(42, 1),
+ PLL_PARAMS(43, 1),
+ PLL_PARAMS(44, 1),
+ PLL_PARAMS(45, 1),
+ PLL_PARAMS(46, 1),
+ PLL_PARAMS(47, 1),
+ PLL_PARAMS(48, 1),
+ PLL_PARAMS(49, 1),
+ PLL_PARAMS(50, 1),
+ PLL_PARAMS(51, 1),
+ PLL_PARAMS(52, 1),
+ PLL_PARAMS(53, 1),
+ PLL_PARAMS(54, 1),
+ PLL_PARAMS(55, 1),
+ PLL_PARAMS(56, 1),
+ PLL_PARAMS(57, 1),
+ PLL_PARAMS(58, 1),
+ PLL_PARAMS(59, 1),
+ PLL_PARAMS(60, 1),
+ PLL_PARAMS(61, 1),
+ PLL_PARAMS(62, 1),
{ /* sentinel */ },
};
-static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
- PLL_RATE(1008000000, 42, 1),
- PLL_RATE(1032000000, 43, 1),
- PLL_RATE(1056000000, 44, 1),
- PLL_RATE(1080000000, 45, 1),
- PLL_RATE(1104000000, 46, 1),
- PLL_RATE(1128000000, 47, 1),
- PLL_RATE(1152000000, 48, 1),
- PLL_RATE(1176000000, 49, 1),
- PLL_RATE(1200000000, 50, 1),
- PLL_RATE(1224000000, 51, 1),
- PLL_RATE(1248000000, 52, 1),
- PLL_RATE(1272000000, 53, 1),
- PLL_RATE(1296000000, 54, 1),
- PLL_RATE(1320000000, 55, 1),
- PLL_RATE(1344000000, 56, 1),
- PLL_RATE(1368000000, 57, 1),
- PLL_RATE(1392000000, 58, 1),
- PLL_RATE(1416000000, 59, 1),
- PLL_RATE(1440000000, 60, 1),
- PLL_RATE(1464000000, 61, 1),
- PLL_RATE(1488000000, 62, 1),
- PLL_RATE(1512000000, 63, 1),
- PLL_RATE(1536000000, 64, 1),
- PLL_RATE(1560000000, 65, 1),
- PLL_RATE(1584000000, 66, 1),
+static const struct pll_params_table gxl_gp0_pll_params_table[] = {
+ PLL_PARAMS(42, 1),
+ PLL_PARAMS(43, 1),
+ PLL_PARAMS(44, 1),
+ PLL_PARAMS(45, 1),
+ PLL_PARAMS(46, 1),
+ PLL_PARAMS(47, 1),
+ PLL_PARAMS(48, 1),
+ PLL_PARAMS(49, 1),
+ PLL_PARAMS(50, 1),
+ PLL_PARAMS(51, 1),
+ PLL_PARAMS(52, 1),
+ PLL_PARAMS(53, 1),
+ PLL_PARAMS(54, 1),
+ PLL_PARAMS(55, 1),
+ PLL_PARAMS(56, 1),
+ PLL_PARAMS(57, 1),
+ PLL_PARAMS(58, 1),
+ PLL_PARAMS(59, 1),
+ PLL_PARAMS(60, 1),
+ PLL_PARAMS(61, 1),
+ PLL_PARAMS(62, 1),
+ PLL_PARAMS(63, 1),
+ PLL_PARAMS(64, 1),
+ PLL_PARAMS(65, 1),
+ PLL_PARAMS(66, 1),
{ /* sentinel */ },
};
.shift = 29,
.width = 1,
},
- .table = gxbb_gp0_pll_rate_table,
+ .table = gxbb_gp0_pll_params_table,
.init_regs = gxbb_gp0_init_regs,
.init_count = ARRAY_SIZE(gxbb_gp0_init_regs),
},
.shift = 29,
.width = 1,
},
- .table = gxl_gp0_pll_rate_table,
+ .table = gxl_gp0_pll_params_table,
.init_regs = gxl_gp0_init_regs,
.init_count = ARRAY_SIZE(gxl_gp0_init_regs),
},
void __iomem *base;
};
-static const struct pll_rate_table sys_pll_rate_table[] = {
- PLL_RATE(1200000000, 50, 1),
- PLL_RATE(1224000000, 51, 1),
- PLL_RATE(1248000000, 52, 1),
- PLL_RATE(1272000000, 53, 1),
- PLL_RATE(1296000000, 54, 1),
- PLL_RATE(1320000000, 55, 1),
- PLL_RATE(1344000000, 56, 1),
- PLL_RATE(1368000000, 57, 1),
- PLL_RATE(1392000000, 58, 1),
- PLL_RATE(1416000000, 59, 1),
- PLL_RATE(1440000000, 60, 1),
- PLL_RATE(1464000000, 61, 1),
- PLL_RATE(1488000000, 62, 1),
- PLL_RATE(1512000000, 63, 1),
- PLL_RATE(1536000000, 64, 1),
+static const struct pll_params_table sys_pll_params_table[] = {
+ PLL_PARAMS(50, 1),
+ PLL_PARAMS(51, 1),
+ PLL_PARAMS(52, 1),
+ PLL_PARAMS(53, 1),
+ PLL_PARAMS(54, 1),
+ PLL_PARAMS(55, 1),
+ PLL_PARAMS(56, 1),
+ PLL_PARAMS(57, 1),
+ PLL_PARAMS(58, 1),
+ PLL_PARAMS(59, 1),
+ PLL_PARAMS(60, 1),
+ PLL_PARAMS(61, 1),
+ PLL_PARAMS(62, 1),
+ PLL_PARAMS(63, 1),
+ PLL_PARAMS(64, 1),
{ /* sentinel */ },
};
.shift = 29,
.width = 1,
},
- .table = sys_pll_rate_table,
+ .table = sys_pll_params_table,
},
.hw.init = &(struct clk_init_data){
.name = "sys_pll_dco",