Skip to content

Commit ecfb9f4

Browse files
pcercueibebarino
authored andcommitted
clk: ingenic: jz4760: Update M/N/OD calculation algorithm
The previous algorithm was pretty broken. - The inner loop had a '(m > m_max)' condition, and the value of 'm' would increase in each iteration; - Each iteration would actually multiply 'm' by two, so it is not needed to re-compute the whole equation at each iteration; - It would loop until (m & 1) == 0, which means it would loop at most once. - The outer loop would divide the 'n' value by two at the end of each iteration. This meant that for a 12 MHz parent clock and a 1.2 GHz requested clock, it would first try n=12, then n=6, then n=3, then n=1, none of which would work; the only valid value is n=2 in this case. Simplify this algorithm with a single for loop, which decrements 'n' after each iteration, addressing all of the above problems. Fixes: bdbfc02 ("clk: ingenic: Add support for the JZ4760") Cc: <[email protected]> Signed-off-by: Paul Cercueil <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Stephen Boyd <[email protected]>
1 parent efaeb5f commit ecfb9f4

File tree

1 file changed

+8
-10
lines changed

1 file changed

+8
-10
lines changed

drivers/clk/ingenic/jz4760-cgu.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,27 +58,25 @@ jz4760_cgu_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info,
5858
unsigned long rate, unsigned long parent_rate,
5959
unsigned int *pm, unsigned int *pn, unsigned int *pod)
6060
{
61-
unsigned int m, n, od, m_max = (1 << pll_info->m_bits) - 2;
61+
unsigned int m, n, od, m_max = (1 << pll_info->m_bits) - 1;
6262

6363
/* The frequency after the N divider must be between 1 and 50 MHz. */
6464
n = parent_rate / (1 * MHZ);
6565

6666
/* The N divider must be >= 2. */
6767
n = clamp_val(n, 2, 1 << pll_info->n_bits);
6868

69-
for (;; n >>= 1) {
70-
od = (unsigned int)-1;
69+
rate /= MHZ;
70+
parent_rate /= MHZ;
7171

72-
do {
73-
m = (rate / MHZ) * (1 << ++od) * n / (parent_rate / MHZ);
74-
} while ((m > m_max || m & 1) && (od < 4));
75-
76-
if (od < 4 && m >= 4 && m <= m_max)
77-
break;
72+
for (m = m_max; m >= m_max && n >= 2; n--) {
73+
m = rate * n / parent_rate;
74+
od = m & 1;
75+
m <<= od;
7876
}
7977

8078
*pm = m;
81-
*pn = n;
79+
*pn = n + 1;
8280
*pod = 1 << od;
8381
}
8482

0 commit comments

Comments
 (0)