Commit 1c26e868 authored by Uwe Kleine-König's avatar Uwe Kleine-König Committed by Luis Henriques

clk: divider: fix selection of divider when rounding to closest

commit 26bac95a 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: 774b5143 (clk: divider: Add round to closest divider)
Signed-off-by: default avatarUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Acked-by: default avatarSascha Hauer <s.hauer@pengutronix.de>
Acked-by: default avatarMaxime Coquelin <maxime.coquelin@st.com>
Signed-off-by: default avatarMichael Turquette <mturquette@linaro.org>
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent f5ea5f84
...@@ -202,6 +202,7 @@ static int _div_round_closest(struct clk_divider *divider, ...@@ -202,6 +202,7 @@ static int _div_round_closest(struct clk_divider *divider,
unsigned long parent_rate, unsigned long rate) unsigned long parent_rate, unsigned long rate)
{ {
int up, down, div; int up, down, div;
unsigned long up_rate, down_rate;
up = down = div = DIV_ROUND_CLOSEST(parent_rate, rate); up = down = div = DIV_ROUND_CLOSEST(parent_rate, rate);
...@@ -213,7 +214,10 @@ static int _div_round_closest(struct clk_divider *divider, ...@@ -213,7 +214,10 @@ static int _div_round_closest(struct clk_divider *divider,
down = _round_down_table(divider->table, div); 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, static int _div_round(struct clk_divider *divider, unsigned long parent_rate,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment