From 55bfef75ea06908d4f30ccfec8f7e239a5592705 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 11 Jan 2011 16:59:55 -0800 Subject: [PATCH] ARM: tegra: clock: Round frequency up in clock dividers When picking clock divider values, the clock framework picks the closest frequency that is lower than the requested frequency. If the value from a clock divider rounds down, and then the new rounded down frequency is requested, it will get rounded down again, resulting in a frequency two steps lower than the original requested frequency. Fix the problem by rounding up when calculating the frequency coming out of a clock divider, so if that frequency is requested again, the same divider value will be picked. Change-Id: Ieaf74448f67d91aeb7ba08226e48c092d8afaa2b Signed-off-by: Colin Cross --- arch/arm/mach-tegra/clock.c | 1 + arch/arm/mach-tegra/tegra2_clocks.c | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index f55697765cdf..e97cc2532aef 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c @@ -143,6 +143,7 @@ static unsigned long clk_predict_rate_from_parent(struct clk *c, struct clk *p) if (c->mul != 0 && c->div != 0) { rate *= c->mul; + rate += c->div / 2; /* round up */ do_div(rate, c->div); } diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c index b59e9c381f85..3dcc11616e90 100644 --- a/arch/arm/mach-tegra/tegra2_clocks.c +++ b/arch/arm/mach-tegra/tegra2_clocks.c @@ -827,9 +827,9 @@ static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate) divider = clk_div71_get_divider(parent_rate, rate); if (divider < 0) return divider; - return parent_rate * 2 / (divider + 2); + return DIV_ROUND_UP(parent_rate * 2, divider + 2); } else if (c->flags & DIV_2) { - return parent_rate / 2; + return DIV_ROUND_UP(parent_rate, 2); } return -EINVAL; } @@ -1006,12 +1006,12 @@ static long tegra2_periph_clk_round_rate(struct clk *c, if (divider < 0) return divider; - return parent_rate * 2 / (divider + 2); + return DIV_ROUND_UP(parent_rate * 2, divider + 2); } else if (c->flags & DIV_U16) { divider = clk_div16_get_divider(parent_rate, rate); if (divider < 0) return divider; - return parent_rate / (divider + 1); + return DIV_ROUND_UP(parent_rate, divider + 1); } return -EINVAL; } -- 2.34.1