summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tcc8k/clock.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/arch/arm/mach-tcc8k/clock.c b/arch/arm/mach-tcc8k/clock.c
index 3970a9cdce26..7ebcbff4652a 100644
--- a/arch/arm/mach-tcc8k/clock.c
+++ b/arch/arm/mach-tcc8k/clock.c
@@ -50,6 +50,8 @@
#define ACLKTCX (CKC_BASE + ACLKTCX_OFFS)
#define ACLKTCZ (CKC_BASE + ACLKTCZ_OFFS)
+#define ACLK_MAX_DIV (0xfff + 1)
+
/* Crystal frequencies */
static unsigned long xi_rate, xti_rate;
@@ -258,14 +260,19 @@ static unsigned long aclk_best_div(struct clk *clk, unsigned long rate)
{
unsigned long div, src, freq, r1, r2;
+ if (!rate)
+ return ACLK_MAX_DIV;
+
src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT;
src &= CLK_SRC_MASK;
freq = root_clk_get_rate(src);
- div = freq / rate + 1;
+ div = freq / rate;
+ if (!div)
+ return 1;
+ if (div >= ACLK_MAX_DIV)
+ return ACLK_MAX_DIV;
r1 = freq / div;
r2 = freq / (div + 1);
- if (r2 >= rate)
- return div + 1;
if ((rate - r2) < (r1 - rate))
return div + 1;
@@ -287,7 +294,8 @@ static int aclk_set_rate(struct clk *clk, unsigned long rate)
u32 reg;
reg = __raw_readl(clk->aclkreg) & ~ACLK_DIV_MASK;
- reg |= aclk_best_div(clk, rate);
+ reg |= aclk_best_div(clk, rate) - 1;
+ __raw_writel(reg, clk->aclkreg);
return 0;
}