From: Uwe Kleine-König Date: Sat, 21 Feb 2015 10:40:24 +0000 (+0100) Subject: clk: divider: fix selection of divider when rounding to closest X-Git-Tag: v3.19.5~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=765c20456c868989e179b14640ebe65347f2f57a;p=thirdparty%2Fkernel%2Fstable.git clk: divider: fix selection of divider when rounding to closest commit 26bac95aa88c2b1747808c0b885abe7814c0165d upstream. It's an invalid approach to assume that among two divider values the one nearer the exact divider is the better one. Assume a parent rate of 1000 Hz, a divider with CLK_DIVIDER_POWER_OF_TWO and a target rate of 89 Hz. The exact divider is ~ 11.236 so 8 and 16 are the candidates to choose from yielding rates 125 Hz and 62.5 Hz respectivly. While 8 is nearer to 11.236 than 16 is, the latter is still the better divider as 62.5 is nearer to 89 than 125 is. Fixes: 774b514390b1 (clk: divider: Add round to closest divider) Signed-off-by: Uwe Kleine-König Acked-by: Sascha Hauer Acked-by: Maxime Coquelin Signed-off-by: Michael Turquette Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index c0a842b335c52..0c0a865c12668 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -208,6 +208,7 @@ static int _div_round_closest(struct clk_divider *divider, unsigned long parent_rate, unsigned long rate) { int up, down, div; + unsigned long up_rate, down_rate; up = down = div = DIV_ROUND_CLOSEST(parent_rate, rate); @@ -219,7 +220,10 @@ static int _div_round_closest(struct clk_divider *divider, down = _round_down_table(divider->table, div); } - return (up - div) <= (div - down) ? up : down; + up_rate = DIV_ROUND_UP(parent_rate, up); + down_rate = DIV_ROUND_UP(parent_rate, down); + + return (rate - up_rate) <= (down_rate - rate) ? up : down; } static int _div_round(struct clk_divider *divider, unsigned long parent_rate,