summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2017-09-05 12:32:41 +0300
committerStephen Boyd <sboyd@codeaurora.org>2017-12-22 05:07:53 +0300
commit448c3c057a1dbb6ecf6e507a3f1a58f5eab21560 (patch)
tree358c0a4e6675ce3f4396baebe422d8aad2f2168d /drivers
parent063578dc5f407f67d149133818efabe457daafda (diff)
downloadlinux-448c3c057a1dbb6ecf6e507a3f1a58f5eab21560.tar.xz
clk: axi-clkgen: Round closest in round_rate() and recalc_rate()
To minimize the rounding error round to the closest integer when calculating the result in the recalc_rate() and set_rate() callbacks. Also in order to improve precision multiply first and then divide. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/clk-axi-clkgen.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index 95a6e9834392..48d11f2598e8 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -302,13 +302,17 @@ static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
unsigned int d, m, dout;
+ unsigned long long tmp;
axi_clkgen_calc_params(*parent_rate, rate, &d, &m, &dout);
if (d == 0 || dout == 0 || m == 0)
return -EINVAL;
- return *parent_rate / d * m / dout;
+ tmp = (unsigned long long)*parent_rate * m;
+ tmp = DIV_ROUND_CLOSEST_ULL(tmp, dout * d);
+
+ return min_t(unsigned long long, tmp, LONG_MAX);
}
static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
@@ -344,8 +348,8 @@ static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
if (d == 0 || dout == 0)
return 0;
- tmp = (unsigned long long)(parent_rate / d) * m;
- do_div(tmp, dout);
+ tmp = (unsigned long long)parent_rate * m;
+ tmp = DIV_ROUND_CLOSEST_ULL(tmp, dout * d);
return min_t(unsigned long long, tmp, ULONG_MAX);
}