Skip to content

Commit 3f0cdb9

Browse files
Ye Liabelvesa
authored andcommitted
clk: imx: pllv4: Fix SPLL2 MULT range
The SPLL2 on iMX8ULP is different with other frac PLLs, it can support VCO from 650Mhz to 1Ghz. According to RM, the MULT is using a range from 27 to 54, not some fixed values. If using current PLL implementation, some clock rate can't be supported. Fix the issue by adding new type for the SPLL2 and use MULT range to replace MULT table Fixes: 5f0601c ("clk: imx: Update the pllv4 to support imx8ulp") Reviewed-by: Peng Fan <peng.fan@nxp.com> Reviewed-by: Jacky Bai <ping.bai@nxp.com> Signed-off-by: Ye Li <ye.li@nxp.com> Signed-off-by: Peng Fan <peng.fan@nxp.com> Reviewed-by: Abel Vesa <abel.vesa@linaro.org> Link: https://lore.kernel.org/r/20230625123340.4067536-1-peng.fan@oss.nxp.com Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
1 parent d3a0946 commit 3f0cdb9

File tree

2 files changed

+37
-10
lines changed

2 files changed

+37
-10
lines changed

drivers/clk/imx/clk-pllv4.c

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,15 @@ struct clk_pllv4 {
4444
u32 cfg_offset;
4545
u32 num_offset;
4646
u32 denom_offset;
47+
bool use_mult_range;
4748
};
4849

4950
/* Valid PLL MULT Table */
5051
static const int pllv4_mult_table[] = {33, 27, 22, 20, 17, 16};
5152

53+
/* Valid PLL MULT range, (max, min) */
54+
static const int pllv4_mult_range[] = {54, 27};
55+
5256
#define to_clk_pllv4(__hw) container_of(__hw, struct clk_pllv4, hw)
5357

5458
#define LOCK_TIMEOUT_US USEC_PER_MSEC
@@ -94,17 +98,30 @@ static unsigned long clk_pllv4_recalc_rate(struct clk_hw *hw,
9498
static long clk_pllv4_round_rate(struct clk_hw *hw, unsigned long rate,
9599
unsigned long *prate)
96100
{
101+
struct clk_pllv4 *pll = to_clk_pllv4(hw);
97102
unsigned long parent_rate = *prate;
98103
unsigned long round_rate, i;
99104
u32 mfn, mfd = DEFAULT_MFD;
100105
bool found = false;
101106
u64 temp64;
102-
103-
for (i = 0; i < ARRAY_SIZE(pllv4_mult_table); i++) {
104-
round_rate = parent_rate * pllv4_mult_table[i];
105-
if (rate >= round_rate) {
107+
u32 mult;
108+
109+
if (pll->use_mult_range) {
110+
temp64 = (u64)rate;
111+
do_div(temp64, parent_rate);
112+
mult = temp64;
113+
if (mult >= pllv4_mult_range[1] &&
114+
mult <= pllv4_mult_range[0]) {
115+
round_rate = parent_rate * mult;
106116
found = true;
107-
break;
117+
}
118+
} else {
119+
for (i = 0; i < ARRAY_SIZE(pllv4_mult_table); i++) {
120+
round_rate = parent_rate * pllv4_mult_table[i];
121+
if (rate >= round_rate) {
122+
found = true;
123+
break;
124+
}
108125
}
109126
}
110127

@@ -138,14 +155,20 @@ static long clk_pllv4_round_rate(struct clk_hw *hw, unsigned long rate,
138155
return round_rate + (u32)temp64;
139156
}
140157

141-
static bool clk_pllv4_is_valid_mult(unsigned int mult)
158+
static bool clk_pllv4_is_valid_mult(struct clk_pllv4 *pll, unsigned int mult)
142159
{
143160
int i;
144161

145162
/* check if mult is in valid MULT table */
146-
for (i = 0; i < ARRAY_SIZE(pllv4_mult_table); i++) {
147-
if (pllv4_mult_table[i] == mult)
163+
if (pll->use_mult_range) {
164+
if (mult >= pllv4_mult_range[1] &&
165+
mult <= pllv4_mult_range[0])
148166
return true;
167+
} else {
168+
for (i = 0; i < ARRAY_SIZE(pllv4_mult_table); i++) {
169+
if (pllv4_mult_table[i] == mult)
170+
return true;
171+
}
149172
}
150173

151174
return false;
@@ -160,7 +183,7 @@ static int clk_pllv4_set_rate(struct clk_hw *hw, unsigned long rate,
160183

161184
mult = rate / parent_rate;
162185

163-
if (!clk_pllv4_is_valid_mult(mult))
186+
if (!clk_pllv4_is_valid_mult(pll, mult))
164187
return -EINVAL;
165188

166189
if (parent_rate <= MAX_MFD)
@@ -227,10 +250,13 @@ struct clk_hw *imx_clk_hw_pllv4(enum imx_pllv4_type type, const char *name,
227250

228251
pll->base = base;
229252

230-
if (type == IMX_PLLV4_IMX8ULP) {
253+
if (type == IMX_PLLV4_IMX8ULP ||
254+
type == IMX_PLLV4_IMX8ULP_1GHZ) {
231255
pll->cfg_offset = IMX8ULP_PLL_CFG_OFFSET;
232256
pll->num_offset = IMX8ULP_PLL_NUM_OFFSET;
233257
pll->denom_offset = IMX8ULP_PLL_DENOM_OFFSET;
258+
if (type == IMX_PLLV4_IMX8ULP_1GHZ)
259+
pll->use_mult_range = true;
234260
} else {
235261
pll->cfg_offset = PLL_CFG_OFFSET;
236262
pll->num_offset = PLL_NUM_OFFSET;

drivers/clk/imx/clk.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ enum imx_pll14xx_type {
4545
enum imx_pllv4_type {
4646
IMX_PLLV4_IMX7ULP,
4747
IMX_PLLV4_IMX8ULP,
48+
IMX_PLLV4_IMX8ULP_1GHZ,
4849
};
4950

5051
enum imx_pfdv2_type {

0 commit comments

Comments
 (0)