diff --git a/arch/arm/mach-tcc8k/clock.c b/arch/arm/mach-tcc8k/clock.c
index 3970a9cdce26e3d3afc39c1d7630639238744769..7ebcbff4652a7af3e948eb3729837b918bb6da39 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;
 }