aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tcc8k/clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tcc8k/clock.c')
-rw-r--r--arch/arm/mach-tcc8k/clock.c38
1 files changed, 26 insertions, 12 deletions
diff --git a/arch/arm/mach-tcc8k/clock.c b/arch/arm/mach-tcc8k/clock.c
index 3970a9cdce26..e7cdae5c77a4 100644
--- a/arch/arm/mach-tcc8k/clock.c
+++ b/arch/arm/mach-tcc8k/clock.c
@@ -45,11 +45,12 @@
45#define ACLKGSB1 (CKC_BASE + ACLKGSB1_OFFS) 45#define ACLKGSB1 (CKC_BASE + ACLKGSB1_OFFS)
46#define ACLKGSB2 (CKC_BASE + ACLKGSB2_OFFS) 46#define ACLKGSB2 (CKC_BASE + ACLKGSB2_OFFS)
47#define ACLKGSB3 (CKC_BASE + ACLKGSB3_OFFS) 47#define ACLKGSB3 (CKC_BASE + ACLKGSB3_OFFS)
48#define ACLKUSBH (CKC_BASE + ACLKUSBH_OFFS)
49#define ACLKTCT (CKC_BASE + ACLKTCT_OFFS) 48#define ACLKTCT (CKC_BASE + ACLKTCT_OFFS)
50#define ACLKTCX (CKC_BASE + ACLKTCX_OFFS) 49#define ACLKTCX (CKC_BASE + ACLKTCX_OFFS)
51#define ACLKTCZ (CKC_BASE + ACLKTCZ_OFFS) 50#define ACLKTCZ (CKC_BASE + ACLKTCZ_OFFS)
52 51
52#define ACLK_MAX_DIV (0xfff + 1)
53
53/* Crystal frequencies */ 54/* Crystal frequencies */
54static unsigned long xi_rate, xti_rate; 55static unsigned long xi_rate, xti_rate;
55 56
@@ -106,9 +107,9 @@ static int root_clk_enable(enum root_clks src)
106 return 0; 107 return 0;
107} 108}
108 109
109static int root_clk_disable(enum root_clks root_src) 110static int root_clk_disable(enum root_clks src)
110{ 111{
111 switch (root_src) { 112 switch (src) {
112 case CLK_SRC_PLL0: return pll_enable(0, 0); 113 case CLK_SRC_PLL0: return pll_enable(0, 0);
113 case CLK_SRC_PLL1: return pll_enable(1, 0); 114 case CLK_SRC_PLL1: return pll_enable(1, 0);
114 case CLK_SRC_PLL2: return pll_enable(2, 0); 115 case CLK_SRC_PLL2: return pll_enable(2, 0);
@@ -197,7 +198,7 @@ static unsigned long get_rate_pll_div(int pll)
197 addr = CKC_BASE + CLKDIVC1_OFFS; 198 addr = CKC_BASE + CLKDIVC1_OFFS;
198 reg = __raw_readl(addr); 199 reg = __raw_readl(addr);
199 if (reg & CLKDIVC1_P2E) 200 if (reg & CLKDIVC1_P2E)
200 div = __raw_readl(addr) & 0x3f; 201 div = reg & 0x3f;
201 break; 202 break;
202 } 203 }
203 return get_rate_pll(pll) / (div + 1); 204 return get_rate_pll(pll) / (div + 1);
@@ -258,14 +259,19 @@ static unsigned long aclk_best_div(struct clk *clk, unsigned long rate)
258{ 259{
259 unsigned long div, src, freq, r1, r2; 260 unsigned long div, src, freq, r1, r2;
260 261
262 if (!rate)
263 return ACLK_MAX_DIV;
264
261 src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT; 265 src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT;
262 src &= CLK_SRC_MASK; 266 src &= CLK_SRC_MASK;
263 freq = root_clk_get_rate(src); 267 freq = root_clk_get_rate(src);
264 div = freq / rate + 1; 268 div = freq / rate;
269 if (!div)
270 return 1;
271 if (div >= ACLK_MAX_DIV)
272 return ACLK_MAX_DIV;
265 r1 = freq / div; 273 r1 = freq / div;
266 r2 = freq / (div + 1); 274 r2 = freq / (div + 1);
267 if (r2 >= rate)
268 return div + 1;
269 if ((rate - r2) < (r1 - rate)) 275 if ((rate - r2) < (r1 - rate))
270 return div + 1; 276 return div + 1;
271 277
@@ -287,7 +293,8 @@ static int aclk_set_rate(struct clk *clk, unsigned long rate)
287 u32 reg; 293 u32 reg;
288 294
289 reg = __raw_readl(clk->aclkreg) & ~ACLK_DIV_MASK; 295 reg = __raw_readl(clk->aclkreg) & ~ACLK_DIV_MASK;
290 reg |= aclk_best_div(clk, rate); 296 reg |= aclk_best_div(clk, rate) - 1;
297 __raw_writel(reg, clk->aclkreg);
291 return 0; 298 return 0;
292} 299}
293 300
@@ -296,15 +303,22 @@ static unsigned long get_rate_sys(struct clk *clk)
296 unsigned int src; 303 unsigned int src;
297 304
298 src = __raw_readl(CKC_BASE + CLKCTRL_OFFS) & CLK_SRC_MASK; 305 src = __raw_readl(CKC_BASE + CLKCTRL_OFFS) & CLK_SRC_MASK;
299 return root_clk_get_rate(src); 306 return root_clk_get_rate(src);
300} 307}
301 308
302static unsigned long get_rate_bus(struct clk *clk) 309static unsigned long get_rate_bus(struct clk *clk)
303{ 310{
304 unsigned int div; 311 unsigned int reg, sdiv, bdiv, rate;
305 312
306 div = (__raw_readl(CKC_BASE + CLKCTRL_OFFS) >> 4) & 0xff; 313 reg = __raw_readl(CKC_BASE + CLKCTRL_OFFS);
307 return get_rate_sys(clk) / (div + 1); 314 rate = get_rate_sys(clk);
315 sdiv = (reg >> 20) & 3;
316 if (sdiv)
317 rate /= sdiv + 1;
318 bdiv = (reg >> 4) & 0xff;
319 if (bdiv)
320 rate /= bdiv + 1;
321 return rate;
308} 322}
309 323
310static unsigned long get_rate_cpu(struct clk *clk) 324static unsigned long get_rate_cpu(struct clk *clk)