diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-02-13 05:04:00 -0500 |
---|---|---|
committer | Mike Turquette <mturquette@linaro.org> | 2014-02-26 21:23:58 -0500 |
commit | 7e50e7e176634e8cc0335778915be75df41043dc (patch) | |
tree | d89e206488b084af24d3336ed2ff42320e0b97c2 | |
parent | b11d282dbea27db1788893115dfca8a7856bf205 (diff) |
clk: ti/divider: fix rate calculation for fractional rates
ti/clk-divider.c does not calculate the rates consistently at the moment.
As an example, on OMAP3 we have a clock divider with a source clock of
864000000 Hz. With dividers 6, 7 and 8 the theoretical rates are:
6: 144000000
7: 123428571.428571...
8: 108000000
Calling clk_round_rate() with the rate in the first column will give the
rate in the second column:
144000000 -> 144000000
143999999 -> 123428571
123428572 -> 123428571
123428571 -> 108000000
Note how clk_round_rate() returns 123428571 for rates from 123428572 to
143999999, which is mathematically correct, but when clk_round_rate() is
called with 123428571, the returned value is surprisingly 108000000.
This means that the following code works a bit oddly:
rate = clk_round_rate(clk, 123428572);
clk_set_rate(clk, rate);
As clk_set_rate() also does clock rate rounding, the result is that the
clock is set to the rate of 108000000, not 123428571 returned by the
clk_round_rate.
This patch changes the ti/clk-divider.c to use DIV_ROUND_UP when
calculating the rate. This gives the following behavior which fixes the
inconsistency:
144000000 -> 144000000
143999999 -> 123428572
123428572 -> 123428572
123428571 -> 108000000
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Signed-off-by: Mike Turquette <mturquette@linaro.org>
-rw-r--r-- | drivers/clk/ti/divider.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c index a15e445570b2..e6aa10db7bba 100644 --- a/drivers/clk/ti/divider.c +++ b/drivers/clk/ti/divider.c | |||
@@ -112,7 +112,7 @@ static unsigned long ti_clk_divider_recalc_rate(struct clk_hw *hw, | |||
112 | return parent_rate; | 112 | return parent_rate; |
113 | } | 113 | } |
114 | 114 | ||
115 | return parent_rate / div; | 115 | return DIV_ROUND_UP(parent_rate, div); |
116 | } | 116 | } |
117 | 117 | ||
118 | /* | 118 | /* |
@@ -182,7 +182,7 @@ static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, | |||
182 | } | 182 | } |
183 | parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), | 183 | parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), |
184 | MULT_ROUND_UP(rate, i)); | 184 | MULT_ROUND_UP(rate, i)); |
185 | now = parent_rate / i; | 185 | now = DIV_ROUND_UP(parent_rate, i); |
186 | if (now <= rate && now > best) { | 186 | if (now <= rate && now > best) { |
187 | bestdiv = i; | 187 | bestdiv = i; |
188 | best = now; | 188 | best = now; |
@@ -205,7 +205,7 @@ static long ti_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, | |||
205 | int div; | 205 | int div; |
206 | div = ti_clk_divider_bestdiv(hw, rate, prate); | 206 | div = ti_clk_divider_bestdiv(hw, rate, prate); |
207 | 207 | ||
208 | return *prate / div; | 208 | return DIV_ROUND_UP(*prate, div); |
209 | } | 209 | } |
210 | 210 | ||
211 | static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, | 211 | static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, |
@@ -216,7 +216,7 @@ static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, | |||
216 | unsigned long flags = 0; | 216 | unsigned long flags = 0; |
217 | u32 val; | 217 | u32 val; |
218 | 218 | ||
219 | div = parent_rate / rate; | 219 | div = DIV_ROUND_UP(parent_rate, rate); |
220 | value = _get_val(divider, div); | 220 | value = _get_val(divider, div); |
221 | 221 | ||
222 | if (value > div_mask(divider)) | 222 | if (value > div_mask(divider)) |