Skip to content

Commit 06030c4

Browse files
lkundrakbebarino
authored andcommitted
clk: mmp: frac: Do not lose last 4 digits of precision
While calculating the output rate of a fractional divider clock, the value is divided and multipled by 10000, discarding the least significant digits -- presumably to fit the intermediate value within 32 bits. The precision we're losing is, however, not insignificant for things like I2S clock. Maybe also elsewhere, now that since commit ea56ad6 ("clk: mmp2: Stop pretending PLL outputs are constant") the parent rates are more precise and no longer rounded to 10000s. Signed-off-by: Lubomir Rintel <[email protected]> Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Stephen Boyd <[email protected]>
1 parent 8f3d9f3 commit 06030c4

File tree

1 file changed

+16
-8
lines changed

1 file changed

+16
-8
lines changed

drivers/clk/mmp/clk-frac.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
2828
unsigned long *prate)
2929
{
3030
struct mmp_clk_factor *factor = to_clk_factor(hw);
31-
unsigned long rate = 0, prev_rate;
31+
u64 rate = 0, prev_rate;
3232
int i;
3333

3434
for (i = 0; i < factor->ftbl_cnt; i++) {
3535
prev_rate = rate;
36-
rate = (((*prate / 10000) * factor->ftbl[i].den) /
37-
(factor->ftbl[i].num * factor->masks->factor)) * 10000;
36+
rate = *prate;
37+
rate *= factor->ftbl[i].den;
38+
do_div(rate, factor->ftbl[i].num * factor->masks->factor);
39+
3840
if (rate > drate)
3941
break;
4042
}
@@ -54,6 +56,7 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
5456
struct mmp_clk_factor *factor = to_clk_factor(hw);
5557
struct mmp_clk_factor_masks *masks = factor->masks;
5658
unsigned int val, num, den;
59+
u64 rate;
5760

5861
val = readl_relaxed(factor->base);
5962

@@ -66,8 +69,11 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
6669
if (!den)
6770
return 0;
6871

69-
return (((parent_rate / 10000) * den) /
70-
(num * factor->masks->factor)) * 10000;
72+
rate = parent_rate;
73+
rate *= den;
74+
do_div(rate, num * factor->masks->factor);
75+
76+
return rate;
7177
}
7278

7379
/* Configures new clock rate*/
@@ -78,12 +84,14 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
7884
struct mmp_clk_factor_masks *masks = factor->masks;
7985
int i;
8086
unsigned long val;
81-
unsigned long rate = 0;
8287
unsigned long flags = 0;
88+
u64 rate = 0;
8389

8490
for (i = 0; i < factor->ftbl_cnt; i++) {
85-
rate = (((prate / 10000) * factor->ftbl[i].den) /
86-
(factor->ftbl[i].num * factor->masks->factor)) * 10000;
91+
rate = prate;
92+
rate *= factor->ftbl[i].den;
93+
do_div(rate, factor->ftbl[i].num * factor->masks->factor);
94+
8795
if (rate > drate)
8896
break;
8997
}

0 commit comments

Comments
 (0)