diff options
-rw-r--r-- | arch/arm/mach-tcc8k/clock.c | 16 |
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 @@ | |||
50 | #define ACLKTCX (CKC_BASE + ACLKTCX_OFFS) | 50 | #define ACLKTCX (CKC_BASE + ACLKTCX_OFFS) |
51 | #define ACLKTCZ (CKC_BASE + ACLKTCZ_OFFS) | 51 | #define ACLKTCZ (CKC_BASE + ACLKTCZ_OFFS) |
52 | 52 | ||
53 | #define ACLK_MAX_DIV (0xfff + 1) | ||
54 | |||
53 | /* Crystal frequencies */ | 55 | /* Crystal frequencies */ |
54 | static unsigned long xi_rate, xti_rate; | 56 | static unsigned long xi_rate, xti_rate; |
55 | 57 | ||
@@ -258,14 +260,19 @@ static unsigned long aclk_best_div(struct clk *clk, unsigned long rate) | |||
258 | { | 260 | { |
259 | unsigned long div, src, freq, r1, r2; | 261 | unsigned long div, src, freq, r1, r2; |
260 | 262 | ||
263 | if (!rate) | ||
264 | return ACLK_MAX_DIV; | ||
265 | |||
261 | src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT; | 266 | src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT; |
262 | src &= CLK_SRC_MASK; | 267 | src &= CLK_SRC_MASK; |
263 | freq = root_clk_get_rate(src); | 268 | freq = root_clk_get_rate(src); |
264 | div = freq / rate + 1; | 269 | div = freq / rate; |
270 | if (!div) | ||
271 | return 1; | ||
272 | if (div >= ACLK_MAX_DIV) | ||
273 | return ACLK_MAX_DIV; | ||
265 | r1 = freq / div; | 274 | r1 = freq / div; |
266 | r2 = freq / (div + 1); | 275 | r2 = freq / (div + 1); |
267 | if (r2 >= rate) | ||
268 | return div + 1; | ||
269 | if ((rate - r2) < (r1 - rate)) | 276 | if ((rate - r2) < (r1 - rate)) |
270 | return div + 1; | 277 | return div + 1; |
271 | 278 | ||
@@ -287,7 +294,8 @@ static int aclk_set_rate(struct clk *clk, unsigned long rate) | |||
287 | u32 reg; | 294 | u32 reg; |
288 | 295 | ||
289 | reg = __raw_readl(clk->aclkreg) & ~ACLK_DIV_MASK; | 296 | reg = __raw_readl(clk->aclkreg) & ~ACLK_DIV_MASK; |
290 | reg |= aclk_best_div(clk, rate); | 297 | reg |= aclk_best_div(clk, rate) - 1; |
298 | __raw_writel(reg, clk->aclkreg); | ||
291 | return 0; | 299 | return 0; |
292 | } | 300 | } |
293 | 301 | ||