5cccd37e |
1 | /* |
2 | * Clock manipulation routines for Freescale STMP37XX/STMP378X |
3 | * |
4 | * Author: Vitaly Wool <vital@embeddedalley.com> |
5 | * |
6 | * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. |
7 | * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. |
8 | */ |
9 | |
10 | /* |
11 | * The code contained herein is licensed under the GNU General Public |
12 | * License. You may obtain a copy of the GNU General Public License |
13 | * Version 2 or later at the following locations: |
14 | * |
15 | * http://www.opensource.org/licenses/gpl-license.html |
16 | * http://www.gnu.org/copyleft/gpl.html |
17 | */ |
98f420b2 |
18 | #define DEBUG |
5cccd37e |
19 | #include <linux/kernel.h> |
20 | #include <linux/module.h> |
21 | #include <linux/init.h> |
22 | #include <linux/clk.h> |
23 | #include <linux/spinlock.h> |
24 | #include <linux/errno.h> |
25 | #include <linux/err.h> |
26 | #include <linux/delay.h> |
27 | #include <linux/io.h> |
6d803ba7 |
28 | #include <linux/clkdev.h> |
5cccd37e |
29 | |
30 | #include <asm/mach-types.h> |
98f420b2 |
31 | #include <mach/platform.h> |
5cccd37e |
32 | #include <mach/regs-clkctrl.h> |
33 | |
34 | #include "clock.h" |
35 | |
36 | static DEFINE_SPINLOCK(clocks_lock); |
37 | |
38 | static struct clk osc_24M; |
39 | static struct clk pll_clk; |
40 | static struct clk cpu_clk; |
41 | static struct clk hclk; |
42 | |
43 | static int propagate_rate(struct clk *); |
44 | |
45 | static inline int clk_is_busy(struct clk *clk) |
46 | { |
47 | return __raw_readl(clk->busy_reg) & (1 << clk->busy_bit); |
48 | } |
49 | |
50 | static inline int clk_good(struct clk *clk) |
51 | { |
52 | return clk && !IS_ERR(clk) && clk->ops; |
53 | } |
54 | |
55 | static int std_clk_enable(struct clk *clk) |
56 | { |
57 | if (clk->enable_reg) { |
58 | u32 clk_reg = __raw_readl(clk->enable_reg); |
59 | if (clk->enable_negate) |
60 | clk_reg &= ~(1 << clk->enable_shift); |
61 | else |
62 | clk_reg |= (1 << clk->enable_shift); |
63 | __raw_writel(clk_reg, clk->enable_reg); |
64 | if (clk->enable_wait) |
65 | udelay(clk->enable_wait); |
66 | return 0; |
67 | } else |
68 | return -EINVAL; |
69 | } |
70 | |
71 | static int std_clk_disable(struct clk *clk) |
72 | { |
73 | if (clk->enable_reg) { |
74 | u32 clk_reg = __raw_readl(clk->enable_reg); |
75 | if (clk->enable_negate) |
76 | clk_reg |= (1 << clk->enable_shift); |
77 | else |
78 | clk_reg &= ~(1 << clk->enable_shift); |
79 | __raw_writel(clk_reg, clk->enable_reg); |
80 | return 0; |
81 | } else |
82 | return -EINVAL; |
83 | } |
84 | |
85 | static int io_set_rate(struct clk *clk, u32 rate) |
86 | { |
87 | u32 reg_frac, clkctrl_frac; |
88 | int i, ret = 0, mask = 0x1f; |
89 | |
90 | clkctrl_frac = (clk->parent->rate * 18 + rate - 1) / rate; |
91 | |
92 | if (clkctrl_frac < 18 || clkctrl_frac > 35) { |
93 | ret = -EINVAL; |
94 | goto out; |
95 | } |
96 | |
97 | reg_frac = __raw_readl(clk->scale_reg); |
98 | reg_frac &= ~(mask << clk->scale_shift); |
99 | __raw_writel(reg_frac | (clkctrl_frac << clk->scale_shift), |
100 | clk->scale_reg); |
101 | if (clk->busy_reg) { |
102 | for (i = 10000; i; i--) |
103 | if (!clk_is_busy(clk)) |
104 | break; |
105 | if (!i) |
106 | ret = -ETIMEDOUT; |
107 | else |
108 | ret = 0; |
109 | } |
110 | out: |
111 | return ret; |
112 | } |
113 | |
114 | static long io_get_rate(struct clk *clk) |
115 | { |
116 | long rate = clk->parent->rate * 18; |
117 | int mask = 0x1f; |
118 | |
119 | rate /= (__raw_readl(clk->scale_reg) >> clk->scale_shift) & mask; |
120 | clk->rate = rate; |
121 | |
122 | return rate; |
123 | } |
124 | |
125 | static long per_get_rate(struct clk *clk) |
126 | { |
127 | long rate = clk->parent->rate; |
128 | long div; |
129 | const int mask = 0xff; |
130 | |
131 | if (clk->enable_reg && |
132 | !(__raw_readl(clk->enable_reg) & clk->enable_shift)) |
133 | clk->rate = 0; |
134 | else { |
135 | div = (__raw_readl(clk->scale_reg) >> clk->scale_shift) & mask; |
136 | if (div) |
137 | rate /= div; |
138 | clk->rate = rate; |
139 | } |
140 | |
141 | return clk->rate; |
142 | } |
143 | |
144 | static int per_set_rate(struct clk *clk, u32 rate) |
145 | { |
146 | int ret = -EINVAL; |
147 | int div = (clk->parent->rate + rate - 1) / rate; |
148 | u32 reg_frac; |
149 | const int mask = 0xff; |
150 | int try = 10; |
151 | int i = -1; |
152 | |
153 | if (div == 0 || div > mask) |
154 | goto out; |
155 | |
156 | reg_frac = __raw_readl(clk->scale_reg); |
157 | reg_frac &= ~(mask << clk->scale_shift); |
158 | |
159 | while (try--) { |
160 | __raw_writel(reg_frac | (div << clk->scale_shift), |
161 | clk->scale_reg); |
162 | |
163 | if (clk->busy_reg) { |
164 | for (i = 10000; i; i--) |
165 | if (!clk_is_busy(clk)) |
166 | break; |
167 | } |
168 | if (i) |
169 | break; |
170 | } |
171 | |
172 | if (!i) |
173 | ret = -ETIMEDOUT; |
174 | else |
175 | ret = 0; |
176 | |
177 | out: |
178 | if (ret != 0) |
179 | printk(KERN_ERR "%s: error %d\n", __func__, ret); |
180 | return ret; |
181 | } |
182 | |
183 | static long lcdif_get_rate(struct clk *clk) |
184 | { |
185 | long rate = clk->parent->rate; |
186 | long div; |
187 | const int mask = 0xff; |
188 | |
189 | div = (__raw_readl(clk->scale_reg) >> clk->scale_shift) & mask; |
190 | if (div) { |
191 | rate /= div; |
98f420b2 |
192 | div = (__raw_readl(REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC) & |
193 | BM_CLKCTRL_FRAC_PIXFRAC) >> BP_CLKCTRL_FRAC_PIXFRAC; |
5cccd37e |
194 | rate /= div; |
195 | } |
196 | clk->rate = rate; |
197 | |
198 | return rate; |
199 | } |
200 | |
201 | static int lcdif_set_rate(struct clk *clk, u32 rate) |
202 | { |
203 | int ret = 0; |
204 | /* |
205 | * On 3700, we can get most timings exact by modifying ref_pix |
206 | * and the divider, but keeping the phase timings at 1 (2 |
207 | * phases per cycle). |
208 | * |
209 | * ref_pix can be between 480e6*18/35=246.9MHz and 480e6*18/18=480MHz, |
210 | * which is between 18/(18*480e6)=2.084ns and 35/(18*480e6)=4.050ns. |
211 | * |
212 | * ns_cycle >= 2*18e3/(18*480) = 25/6 |
213 | * ns_cycle <= 2*35e3/(18*480) = 875/108 |
214 | * |
215 | * Multiply the ns_cycle by 'div' to lengthen it until it fits the |
216 | * bounds. This is the divider we'll use after ref_pix. |
217 | * |
218 | * 6 * ns_cycle >= 25 * div |
219 | * 108 * ns_cycle <= 875 * div |
220 | */ |
221 | u32 ns_cycle = 1000000 / rate; |
222 | u32 div, reg_val; |
223 | u32 lowest_result = (u32) -1; |
224 | u32 lowest_div = 0, lowest_fracdiv = 0; |
225 | |
226 | for (div = 1; div < 256; ++div) { |
227 | u32 fracdiv; |
228 | u32 ps_result; |
229 | int lower_bound = 6 * ns_cycle >= 25 * div; |
230 | int upper_bound = 108 * ns_cycle <= 875 * div; |
231 | if (!lower_bound) |
232 | break; |
233 | if (!upper_bound) |
234 | continue; |
235 | /* |
236 | * Found a matching div. Calculate fractional divider needed, |
237 | * rounded up. |
238 | */ |
239 | fracdiv = ((clk->parent->rate / 1000 * 18 / 2) * |
240 | ns_cycle + 1000 * div - 1) / |
241 | (1000 * div); |
242 | if (fracdiv < 18 || fracdiv > 35) { |
243 | ret = -EINVAL; |
244 | goto out; |
245 | } |
246 | /* Calculate the actual cycle time this results in */ |
247 | ps_result = 6250 * div * fracdiv / 27; |
248 | |
249 | /* Use the fastest result that doesn't break ns_cycle */ |
250 | if (ps_result <= lowest_result) { |
251 | lowest_result = ps_result; |
252 | lowest_div = div; |
253 | lowest_fracdiv = fracdiv; |
254 | } |
255 | } |
256 | |
257 | if (div >= 256 || lowest_result == (u32) -1) { |
258 | ret = -EINVAL; |
259 | goto out; |
260 | } |
261 | pr_debug("Programming PFD=%u,DIV=%u ref_pix=%uMHz " |
262 | "PIXCLK=%uMHz cycle=%u.%03uns\n", |
263 | lowest_fracdiv, lowest_div, |
264 | 480*18/lowest_fracdiv, 480*18/lowest_fracdiv/lowest_div, |
265 | lowest_result / 1000, lowest_result % 1000); |
266 | |
267 | /* Program ref_pix phase fractional divider */ |
98f420b2 |
268 | reg_val = __raw_readl(REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC); |
269 | reg_val &= ~BM_CLKCTRL_FRAC_PIXFRAC; |
270 | reg_val |= BF(lowest_fracdiv, CLKCTRL_FRAC_PIXFRAC); |
271 | __raw_writel(reg_val, REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC); |
272 | |
5cccd37e |
273 | /* Ungate PFD */ |
98f420b2 |
274 | stmp3xxx_clearl(BM_CLKCTRL_FRAC_CLKGATEPIX, |
275 | REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC); |
5cccd37e |
276 | |
277 | /* Program pix divider */ |
278 | reg_val = __raw_readl(clk->scale_reg); |
279 | reg_val &= ~(BM_CLKCTRL_PIX_DIV | BM_CLKCTRL_PIX_CLKGATE); |
98f420b2 |
280 | reg_val |= BF(lowest_div, CLKCTRL_PIX_DIV); |
5cccd37e |
281 | __raw_writel(reg_val, clk->scale_reg); |
282 | |
283 | /* Wait for divider update */ |
284 | if (clk->busy_reg) { |
285 | int i; |
286 | for (i = 10000; i; i--) |
287 | if (!clk_is_busy(clk)) |
288 | break; |
289 | if (!i) { |
290 | ret = -ETIMEDOUT; |
291 | goto out; |
292 | } |
293 | } |
294 | |
295 | /* Switch to ref_pix source */ |
98f420b2 |
296 | reg_val = __raw_readl(REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ); |
297 | reg_val &= ~BM_CLKCTRL_CLKSEQ_BYPASS_PIX; |
298 | __raw_writel(reg_val, REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ); |
5cccd37e |
299 | |
300 | out: |
301 | return ret; |
302 | } |
303 | |
304 | |
305 | static int cpu_set_rate(struct clk *clk, u32 rate) |
306 | { |
98f420b2 |
307 | u32 reg_val; |
308 | |
5cccd37e |
309 | if (rate < 24000) |
310 | return -EINVAL; |
311 | else if (rate == 24000) { |
312 | /* switch to the 24M source */ |
313 | clk_set_parent(clk, &osc_24M); |
314 | } else { |
315 | int i; |
316 | u32 clkctrl_cpu = 1; |
317 | u32 c = clkctrl_cpu; |
318 | u32 clkctrl_frac = 1; |
319 | u32 val; |
320 | for ( ; c < 0x40; c++) { |
321 | u32 f = (pll_clk.rate*18/c + rate/2) / rate; |
322 | int s1, s2; |
323 | |
324 | if (f < 18 || f > 35) |
325 | continue; |
326 | s1 = pll_clk.rate*18/clkctrl_frac/clkctrl_cpu - rate; |
327 | s2 = pll_clk.rate*18/c/f - rate; |
328 | pr_debug("%s: s1 %d, s2 %d\n", __func__, s1, s2); |
329 | if (abs(s1) > abs(s2)) { |
330 | clkctrl_cpu = c; |
331 | clkctrl_frac = f; |
332 | } |
333 | if (s2 == 0) |
334 | break; |
335 | }; |
336 | pr_debug("%s: clkctrl_cpu %d, clkctrl_frac %d\n", __func__, |
337 | clkctrl_cpu, clkctrl_frac); |
338 | if (c == 0x40) { |
339 | int d = pll_clk.rate*18/clkctrl_frac/clkctrl_cpu - |
340 | rate; |
341 | if (abs(d) > 100 || |
342 | clkctrl_frac < 18 || clkctrl_frac > 35) |
343 | return -EINVAL; |
344 | } |
345 | |
346 | /* 4.6.2 */ |
347 | val = __raw_readl(clk->scale_reg); |
348 | val &= ~(0x3f << clk->scale_shift); |
349 | val |= clkctrl_frac; |
350 | clk_set_parent(clk, &osc_24M); |
351 | udelay(10); |
352 | __raw_writel(val, clk->scale_reg); |
353 | /* ungate */ |
354 | __raw_writel(1<<7, clk->scale_reg + 8); |
355 | /* write clkctrl_cpu */ |
356 | clk->saved_div = clkctrl_cpu; |
98f420b2 |
357 | |
358 | reg_val = __raw_readl(REGS_CLKCTRL_BASE + HW_CLKCTRL_CPU); |
359 | reg_val &= ~0x3F; |
360 | reg_val |= clkctrl_cpu; |
361 | __raw_writel(reg_val, REGS_CLKCTRL_BASE + HW_CLKCTRL_CPU); |
362 | |
5cccd37e |
363 | for (i = 10000; i; i--) |
364 | if (!clk_is_busy(clk)) |
365 | break; |
366 | if (!i) { |
367 | printk(KERN_ERR "couldn't set up CPU divisor\n"); |
368 | return -ETIMEDOUT; |
369 | } |
370 | clk_set_parent(clk, &pll_clk); |
371 | clk->saved_div = 0; |
372 | udelay(10); |
373 | } |
374 | return 0; |
375 | } |
376 | |
377 | static long cpu_get_rate(struct clk *clk) |
378 | { |
379 | long rate = clk->parent->rate * 18; |
380 | |
381 | rate /= (__raw_readl(clk->scale_reg) >> clk->scale_shift) & 0x3f; |
98f420b2 |
382 | rate /= __raw_readl(REGS_CLKCTRL_BASE + HW_CLKCTRL_CPU) & 0x3f; |
5cccd37e |
383 | rate = ((rate + 9) / 10) * 10; |
384 | clk->rate = rate; |
385 | |
386 | return rate; |
387 | } |
388 | |
389 | static long cpu_round_rate(struct clk *clk, u32 rate) |
390 | { |
391 | unsigned long r = 0; |
392 | |
393 | if (rate <= 24000) |
394 | r = 24000; |
395 | else { |
396 | u32 clkctrl_cpu = 1; |
397 | u32 clkctrl_frac; |
398 | do { |
399 | clkctrl_frac = |
400 | (pll_clk.rate*18 / clkctrl_cpu + rate/2) / rate; |
401 | if (clkctrl_frac > 35) |
402 | continue; |
403 | if (pll_clk.rate*18 / clkctrl_frac / clkctrl_cpu/10 == |
404 | rate / 10) |
405 | break; |
406 | } while (pll_clk.rate / 2 >= clkctrl_cpu++ * rate); |
407 | if (pll_clk.rate / 2 < (clkctrl_cpu - 1) * rate) |
408 | clkctrl_cpu--; |
409 | pr_debug("%s: clkctrl_cpu %d, clkctrl_frac %d\n", __func__, |
410 | clkctrl_cpu, clkctrl_frac); |
411 | if (clkctrl_frac < 18) |
412 | clkctrl_frac = 18; |
413 | if (clkctrl_frac > 35) |
414 | clkctrl_frac = 35; |
415 | |
416 | r = pll_clk.rate * 18; |
417 | r /= clkctrl_frac; |
418 | r /= clkctrl_cpu; |
419 | r = 10 * ((r + 9) / 10); |
420 | } |
421 | return r; |
422 | } |
423 | |
424 | static long emi_get_rate(struct clk *clk) |
425 | { |
426 | long rate = clk->parent->rate * 18; |
427 | |
428 | rate /= (__raw_readl(clk->scale_reg) >> clk->scale_shift) & 0x3f; |
98f420b2 |
429 | rate /= __raw_readl(REGS_CLKCTRL_BASE + HW_CLKCTRL_EMI) & 0x3f; |
5cccd37e |
430 | clk->rate = rate; |
431 | |
432 | return rate; |
433 | } |
434 | |
435 | static int clkseq_set_parent(struct clk *clk, struct clk *parent) |
436 | { |
437 | int ret = -EINVAL; |
438 | int shift = 8; |
439 | |
440 | /* bypass? */ |
441 | if (parent == &osc_24M) |
442 | shift = 4; |
443 | |
444 | if (clk->bypass_reg) { |
98f420b2 |
445 | #ifdef CONFIG_ARCH_STMP378X |
446 | u32 hbus_val, cpu_val; |
5cccd37e |
447 | |
448 | if (clk == &cpu_clk && shift == 4) { |
98f420b2 |
449 | hbus_val = __raw_readl(REGS_CLKCTRL_BASE + |
450 | HW_CLKCTRL_HBUS); |
451 | cpu_val = __raw_readl(REGS_CLKCTRL_BASE + |
452 | HW_CLKCTRL_CPU); |
453 | |
454 | hbus_val &= ~(BM_CLKCTRL_HBUS_DIV_FRAC_EN | |
455 | BM_CLKCTRL_HBUS_DIV); |
5cccd37e |
456 | clk->saved_div = cpu_val & BM_CLKCTRL_CPU_DIV_CPU; |
457 | cpu_val &= ~BM_CLKCTRL_CPU_DIV_CPU; |
458 | cpu_val |= 1; |
98f420b2 |
459 | |
5cccd37e |
460 | if (machine_is_stmp378x()) { |
98f420b2 |
461 | __raw_writel(hbus_val, |
462 | REGS_CLKCTRL_BASE + HW_CLKCTRL_HBUS); |
463 | __raw_writel(cpu_val, |
464 | REGS_CLKCTRL_BASE + HW_CLKCTRL_CPU); |
5cccd37e |
465 | hclk.rate = 0; |
466 | } |
467 | } else if (clk == &cpu_clk && shift == 8) { |
98f420b2 |
468 | hbus_val = __raw_readl(REGS_CLKCTRL_BASE + |
469 | HW_CLKCTRL_HBUS); |
470 | cpu_val = __raw_readl(REGS_CLKCTRL_BASE + |
471 | HW_CLKCTRL_CPU); |
472 | hbus_val &= ~(BM_CLKCTRL_HBUS_DIV_FRAC_EN | |
473 | BM_CLKCTRL_HBUS_DIV); |
5cccd37e |
474 | hbus_val |= 2; |
475 | cpu_val &= ~BM_CLKCTRL_CPU_DIV_CPU; |
476 | if (clk->saved_div) |
477 | cpu_val |= clk->saved_div; |
478 | else |
479 | cpu_val |= 2; |
98f420b2 |
480 | |
5cccd37e |
481 | if (machine_is_stmp378x()) { |
98f420b2 |
482 | __raw_writel(hbus_val, |
483 | REGS_CLKCTRL_BASE + HW_CLKCTRL_HBUS); |
484 | __raw_writel(cpu_val, |
485 | REGS_CLKCTRL_BASE + HW_CLKCTRL_CPU); |
5cccd37e |
486 | hclk.rate = 0; |
487 | } |
98f420b2 |
488 | } |
489 | #endif |
490 | __raw_writel(1 << clk->bypass_shift, clk->bypass_reg + shift); |
5cccd37e |
491 | |
492 | ret = 0; |
493 | } |
494 | |
495 | return ret; |
496 | } |
497 | |
498 | static int hbus_set_rate(struct clk *clk, u32 rate) |
499 | { |
500 | u8 div = 0; |
501 | int is_frac = 0; |
502 | u32 clkctrl_hbus; |
503 | struct clk *parent = clk->parent; |
504 | |
505 | pr_debug("%s: rate %d, parent rate %d\n", __func__, rate, |
506 | parent->rate); |
507 | |
508 | if (rate > parent->rate) |
509 | return -EINVAL; |
510 | |
511 | if (((parent->rate + rate/2) / rate) * rate != parent->rate && |
512 | parent->rate / rate < 32) { |
513 | pr_debug("%s: switching to fractional mode\n", __func__); |
514 | is_frac = 1; |
515 | } |
516 | |
517 | if (is_frac) |
518 | div = (32 * rate + parent->rate / 2) / parent->rate; |
519 | else |
520 | div = (parent->rate + rate - 1) / rate; |
521 | pr_debug("%s: div calculated is %d\n", __func__, div); |
522 | if (!div || div > 0x1f) |
523 | return -EINVAL; |
524 | |
525 | clk_set_parent(&cpu_clk, &osc_24M); |
526 | udelay(10); |
527 | clkctrl_hbus = __raw_readl(clk->scale_reg); |
528 | clkctrl_hbus &= ~0x3f; |
529 | clkctrl_hbus |= div; |
530 | clkctrl_hbus |= (is_frac << 5); |
531 | |
532 | __raw_writel(clkctrl_hbus, clk->scale_reg); |
533 | if (clk->busy_reg) { |
534 | int i; |
535 | for (i = 10000; i; i--) |
536 | if (!clk_is_busy(clk)) |
537 | break; |
538 | if (!i) { |
539 | printk(KERN_ERR "couldn't set up CPU divisor\n"); |
540 | return -ETIMEDOUT; |
541 | } |
542 | } |
543 | clk_set_parent(&cpu_clk, &pll_clk); |
544 | __raw_writel(clkctrl_hbus, clk->scale_reg); |
545 | udelay(10); |
546 | return 0; |
547 | } |
548 | |
549 | static long hbus_get_rate(struct clk *clk) |
550 | { |
551 | long rate = clk->parent->rate; |
552 | |
553 | if (__raw_readl(clk->scale_reg) & 0x20) { |
554 | rate *= __raw_readl(clk->scale_reg) & 0x1f; |
555 | rate /= 32; |
556 | } else |
557 | rate /= __raw_readl(clk->scale_reg) & 0x1f; |
558 | clk->rate = rate; |
559 | |
560 | return rate; |
561 | } |
562 | |
563 | static int xbus_set_rate(struct clk *clk, u32 rate) |
564 | { |
565 | u16 div = 0; |
566 | u32 clkctrl_xbus; |
567 | |
568 | pr_debug("%s: rate %d, parent rate %d\n", __func__, rate, |
569 | clk->parent->rate); |
570 | |
571 | div = (clk->parent->rate + rate - 1) / rate; |
572 | pr_debug("%s: div calculated is %d\n", __func__, div); |
573 | if (!div || div > 0x3ff) |
574 | return -EINVAL; |
575 | |
576 | clkctrl_xbus = __raw_readl(clk->scale_reg); |
577 | clkctrl_xbus &= ~0x3ff; |
578 | clkctrl_xbus |= div; |
579 | __raw_writel(clkctrl_xbus, clk->scale_reg); |
580 | if (clk->busy_reg) { |
581 | int i; |
582 | for (i = 10000; i; i--) |
583 | if (!clk_is_busy(clk)) |
584 | break; |
585 | if (!i) { |
586 | printk(KERN_ERR "couldn't set up xbus divisor\n"); |
587 | return -ETIMEDOUT; |
588 | } |
589 | } |
590 | return 0; |
591 | } |
592 | |
593 | static long xbus_get_rate(struct clk *clk) |
594 | { |
595 | long rate = clk->parent->rate; |
596 | |
597 | rate /= __raw_readl(clk->scale_reg) & 0x3ff; |
598 | clk->rate = rate; |
599 | |
600 | return rate; |
601 | } |
602 | |
603 | |
604 | /* Clock ops */ |
605 | |
606 | static struct clk_ops std_ops = { |
607 | .enable = std_clk_enable, |
608 | .disable = std_clk_disable, |
609 | .get_rate = per_get_rate, |
610 | .set_rate = per_set_rate, |
611 | .set_parent = clkseq_set_parent, |
612 | }; |
613 | |
614 | static struct clk_ops min_ops = { |
615 | .enable = std_clk_enable, |
616 | .disable = std_clk_disable, |
617 | }; |
618 | |
619 | static struct clk_ops cpu_ops = { |
620 | .enable = std_clk_enable, |
621 | .disable = std_clk_disable, |
622 | .get_rate = cpu_get_rate, |
623 | .set_rate = cpu_set_rate, |
624 | .round_rate = cpu_round_rate, |
625 | .set_parent = clkseq_set_parent, |
626 | }; |
627 | |
628 | static struct clk_ops io_ops = { |
629 | .enable = std_clk_enable, |
630 | .disable = std_clk_disable, |
631 | .get_rate = io_get_rate, |
632 | .set_rate = io_set_rate, |
633 | }; |
634 | |
635 | static struct clk_ops hbus_ops = { |
636 | .get_rate = hbus_get_rate, |
637 | .set_rate = hbus_set_rate, |
638 | }; |
639 | |
640 | static struct clk_ops xbus_ops = { |
641 | .get_rate = xbus_get_rate, |
642 | .set_rate = xbus_set_rate, |
643 | }; |
644 | |
645 | static struct clk_ops lcdif_ops = { |
646 | .enable = std_clk_enable, |
647 | .disable = std_clk_disable, |
648 | .get_rate = lcdif_get_rate, |
649 | .set_rate = lcdif_set_rate, |
650 | .set_parent = clkseq_set_parent, |
651 | }; |
652 | |
653 | static struct clk_ops emi_ops = { |
654 | .get_rate = emi_get_rate, |
655 | }; |
656 | |
657 | /* List of on-chip clocks */ |
658 | |
659 | static struct clk osc_24M = { |
660 | .flags = FIXED_RATE | ENABLED, |
661 | .rate = 24000, |
662 | }; |
663 | |
664 | static struct clk pll_clk = { |
665 | .parent = &osc_24M, |
98f420b2 |
666 | .enable_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_PLLCTRL0, |
5cccd37e |
667 | .enable_shift = 16, |
668 | .enable_wait = 10, |
669 | .flags = FIXED_RATE | ENABLED, |
670 | .rate = 480000, |
671 | .ops = &min_ops, |
672 | }; |
673 | |
674 | static struct clk cpu_clk = { |
675 | .parent = &pll_clk, |
98f420b2 |
676 | .scale_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC, |
5cccd37e |
677 | .scale_shift = 0, |
98f420b2 |
678 | .bypass_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ, |
5cccd37e |
679 | .bypass_shift = 7, |
98f420b2 |
680 | .busy_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_CPU, |
5cccd37e |
681 | .busy_bit = 28, |
682 | .flags = RATE_PROPAGATES | ENABLED, |
683 | .ops = &cpu_ops, |
684 | }; |
685 | |
686 | static struct clk io_clk = { |
687 | .parent = &pll_clk, |
98f420b2 |
688 | .enable_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC, |
5cccd37e |
689 | .enable_shift = 31, |
690 | .enable_negate = 1, |
98f420b2 |
691 | .scale_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC, |
5cccd37e |
692 | .scale_shift = 24, |
693 | .flags = RATE_PROPAGATES | ENABLED, |
694 | .ops = &io_ops, |
695 | }; |
696 | |
697 | static struct clk hclk = { |
698 | .parent = &cpu_clk, |
98f420b2 |
699 | .scale_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_HBUS, |
700 | .bypass_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ, |
5cccd37e |
701 | .bypass_shift = 7, |
98f420b2 |
702 | .busy_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_HBUS, |
5cccd37e |
703 | .busy_bit = 29, |
704 | .flags = RATE_PROPAGATES | ENABLED, |
705 | .ops = &hbus_ops, |
706 | }; |
707 | |
708 | static struct clk xclk = { |
709 | .parent = &osc_24M, |
98f420b2 |
710 | .scale_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_XBUS, |
711 | .busy_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_XBUS, |
5cccd37e |
712 | .busy_bit = 31, |
713 | .flags = RATE_PROPAGATES | ENABLED, |
714 | .ops = &xbus_ops, |
715 | }; |
716 | |
717 | static struct clk uart_clk = { |
718 | .parent = &xclk, |
98f420b2 |
719 | .enable_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_XTAL, |
5cccd37e |
720 | .enable_shift = 31, |
721 | .enable_negate = 1, |
722 | .flags = ENABLED, |
723 | .ops = &min_ops, |
724 | }; |
725 | |
726 | static struct clk audio_clk = { |
727 | .parent = &xclk, |
98f420b2 |
728 | .enable_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_XTAL, |
5cccd37e |
729 | .enable_shift = 30, |
730 | .enable_negate = 1, |
731 | .ops = &min_ops, |
732 | }; |
733 | |
734 | static struct clk pwm_clk = { |
735 | .parent = &xclk, |
98f420b2 |
736 | .enable_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_XTAL, |
5cccd37e |
737 | .enable_shift = 29, |
738 | .enable_negate = 1, |
739 | .ops = &min_ops, |
740 | }; |
741 | |
742 | static struct clk dri_clk = { |
743 | .parent = &xclk, |
98f420b2 |
744 | .enable_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_XTAL, |
5cccd37e |
745 | .enable_shift = 28, |
746 | .enable_negate = 1, |
747 | .ops = &min_ops, |
748 | }; |
749 | |
750 | static struct clk digctl_clk = { |
751 | .parent = &xclk, |
98f420b2 |
752 | .enable_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_XTAL, |
5cccd37e |
753 | .enable_shift = 27, |
754 | .enable_negate = 1, |
755 | .ops = &min_ops, |
756 | }; |
757 | |
758 | static struct clk timer_clk = { |
759 | .parent = &xclk, |
98f420b2 |
760 | .enable_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_XTAL, |
5cccd37e |
761 | .enable_shift = 26, |
762 | .enable_negate = 1, |
763 | .flags = ENABLED, |
764 | .ops = &min_ops, |
765 | }; |
766 | |
767 | static struct clk lcdif_clk = { |
768 | .parent = &pll_clk, |
98f420b2 |
769 | .scale_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_PIX, |
770 | .busy_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_PIX, |
5cccd37e |
771 | .busy_bit = 29, |
98f420b2 |
772 | .enable_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_PIX, |
5cccd37e |
773 | .enable_shift = 31, |
774 | .enable_negate = 1, |
98f420b2 |
775 | .bypass_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ, |
5cccd37e |
776 | .bypass_shift = 1, |
777 | .flags = NEEDS_SET_PARENT, |
778 | .ops = &lcdif_ops, |
779 | }; |
780 | |
781 | static struct clk ssp_clk = { |
782 | .parent = &io_clk, |
98f420b2 |
783 | .scale_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_SSP, |
784 | .busy_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_SSP, |
5cccd37e |
785 | .busy_bit = 29, |
98f420b2 |
786 | .enable_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_SSP, |
5cccd37e |
787 | .enable_shift = 31, |
98f420b2 |
788 | .bypass_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ, |
5cccd37e |
789 | .bypass_shift = 5, |
790 | .enable_negate = 1, |
791 | .flags = NEEDS_SET_PARENT, |
792 | .ops = &std_ops, |
793 | }; |
794 | |
795 | static struct clk gpmi_clk = { |
796 | .parent = &io_clk, |
98f420b2 |
797 | .scale_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_GPMI, |
798 | .busy_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_GPMI, |
5cccd37e |
799 | .busy_bit = 29, |
98f420b2 |
800 | .enable_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_GPMI, |
5cccd37e |
801 | .enable_shift = 31, |
802 | .enable_negate = 1, |
98f420b2 |
803 | .bypass_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ, |
5cccd37e |
804 | .bypass_shift = 4, |
805 | .flags = NEEDS_SET_PARENT, |
806 | .ops = &std_ops, |
807 | }; |
808 | |
809 | static struct clk spdif_clk = { |
810 | .parent = &pll_clk, |
98f420b2 |
811 | .enable_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_SPDIF, |
5cccd37e |
812 | .enable_shift = 31, |
813 | .enable_negate = 1, |
814 | .ops = &min_ops, |
815 | }; |
816 | |
817 | static struct clk emi_clk = { |
818 | .parent = &pll_clk, |
98f420b2 |
819 | .enable_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_EMI, |
5cccd37e |
820 | .enable_shift = 31, |
821 | .enable_negate = 1, |
98f420b2 |
822 | .scale_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC, |
5cccd37e |
823 | .scale_shift = 8, |
98f420b2 |
824 | .busy_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_EMI, |
5cccd37e |
825 | .busy_bit = 28, |
98f420b2 |
826 | .bypass_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ, |
5cccd37e |
827 | .bypass_shift = 6, |
828 | .flags = ENABLED, |
829 | .ops = &emi_ops, |
830 | }; |
831 | |
832 | static struct clk ir_clk = { |
833 | .parent = &io_clk, |
98f420b2 |
834 | .enable_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_IR, |
5cccd37e |
835 | .enable_shift = 31, |
836 | .enable_negate = 1, |
98f420b2 |
837 | .bypass_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ, |
5cccd37e |
838 | .bypass_shift = 3, |
839 | .ops = &min_ops, |
840 | }; |
841 | |
842 | static struct clk saif_clk = { |
843 | .parent = &pll_clk, |
98f420b2 |
844 | .scale_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_SAIF, |
845 | .busy_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_SAIF, |
5cccd37e |
846 | .busy_bit = 29, |
98f420b2 |
847 | .enable_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_SAIF, |
5cccd37e |
848 | .enable_shift = 31, |
849 | .enable_negate = 1, |
98f420b2 |
850 | .bypass_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ, |
5cccd37e |
851 | .bypass_shift = 0, |
852 | .ops = &std_ops, |
853 | }; |
854 | |
855 | static struct clk usb_clk = { |
856 | .parent = &pll_clk, |
98f420b2 |
857 | .enable_reg = REGS_CLKCTRL_BASE + HW_CLKCTRL_PLLCTRL0, |
5cccd37e |
858 | .enable_shift = 18, |
859 | .enable_negate = 1, |
860 | .ops = &min_ops, |
861 | }; |
862 | |
863 | /* list of all the clocks */ |
98f420b2 |
864 | static struct clk_lookup onchip_clks[] = { |
5cccd37e |
865 | { |
866 | .con_id = "osc_24M", |
867 | .clk = &osc_24M, |
868 | }, { |
869 | .con_id = "pll", |
870 | .clk = &pll_clk, |
871 | }, { |
872 | .con_id = "cpu", |
873 | .clk = &cpu_clk, |
874 | }, { |
875 | .con_id = "hclk", |
876 | .clk = &hclk, |
877 | }, { |
878 | .con_id = "xclk", |
879 | .clk = &xclk, |
880 | }, { |
881 | .con_id = "io", |
882 | .clk = &io_clk, |
883 | }, { |
884 | .con_id = "uart", |
885 | .clk = &uart_clk, |
886 | }, { |
887 | .con_id = "audio", |
888 | .clk = &audio_clk, |
889 | }, { |
890 | .con_id = "pwm", |
891 | .clk = &pwm_clk, |
892 | }, { |
893 | .con_id = "dri", |
894 | .clk = &dri_clk, |
895 | }, { |
896 | .con_id = "digctl", |
897 | .clk = &digctl_clk, |
898 | }, { |
899 | .con_id = "timer", |
900 | .clk = &timer_clk, |
901 | }, { |
902 | .con_id = "lcdif", |
903 | .clk = &lcdif_clk, |
904 | }, { |
905 | .con_id = "ssp", |
906 | .clk = &ssp_clk, |
907 | }, { |
908 | .con_id = "gpmi", |
909 | .clk = &gpmi_clk, |
910 | }, { |
911 | .con_id = "spdif", |
912 | .clk = &spdif_clk, |
913 | }, { |
914 | .con_id = "emi", |
915 | .clk = &emi_clk, |
916 | }, { |
917 | .con_id = "ir", |
918 | .clk = &ir_clk, |
919 | }, { |
920 | .con_id = "saif", |
921 | .clk = &saif_clk, |
922 | }, { |
923 | .con_id = "usb", |
924 | .clk = &usb_clk, |
925 | }, |
926 | }; |
927 | |
928 | static int __init propagate_rate(struct clk *clk) |
929 | { |
930 | struct clk_lookup *cl; |
931 | |
932 | for (cl = onchip_clks; cl < onchip_clks + ARRAY_SIZE(onchip_clks); |
933 | cl++) { |
934 | if (unlikely(!clk_good(cl->clk))) |
935 | continue; |
936 | if (cl->clk->parent == clk && cl->clk->ops->get_rate) { |
937 | cl->clk->ops->get_rate(cl->clk); |
938 | if (cl->clk->flags & RATE_PROPAGATES) |
939 | propagate_rate(cl->clk); |
940 | } |
941 | } |
942 | |
943 | return 0; |
944 | } |
945 | |
946 | /* Exported API */ |
947 | unsigned long clk_get_rate(struct clk *clk) |
948 | { |
949 | if (unlikely(!clk_good(clk))) |
950 | return 0; |
951 | |
952 | if (clk->rate != 0) |
953 | return clk->rate; |
954 | |
955 | if (clk->ops->get_rate != NULL) |
956 | return clk->ops->get_rate(clk); |
957 | |
958 | return clk_get_rate(clk->parent); |
959 | } |
960 | EXPORT_SYMBOL(clk_get_rate); |
961 | |
962 | long clk_round_rate(struct clk *clk, unsigned long rate) |
963 | { |
964 | if (unlikely(!clk_good(clk))) |
965 | return 0; |
966 | |
967 | if (clk->ops->round_rate) |
968 | return clk->ops->round_rate(clk, rate); |
969 | |
970 | return 0; |
971 | } |
972 | EXPORT_SYMBOL(clk_round_rate); |
973 | |
974 | static inline int close_enough(long rate1, long rate2) |
975 | { |
976 | return rate1 && !((rate2 - rate1) * 1000 / rate1); |
977 | } |
978 | |
979 | int clk_set_rate(struct clk *clk, unsigned long rate) |
980 | { |
981 | int ret = -EINVAL; |
982 | |
983 | if (unlikely(!clk_good(clk))) |
984 | goto out; |
985 | |
986 | if (clk->flags & FIXED_RATE || !clk->ops->set_rate) |
987 | goto out; |
988 | |
989 | else if (!close_enough(clk->rate, rate)) { |
990 | ret = clk->ops->set_rate(clk, rate); |
991 | if (ret < 0) |
992 | goto out; |
993 | clk->rate = rate; |
994 | if (clk->flags & RATE_PROPAGATES) |
995 | propagate_rate(clk); |
996 | } else |
997 | ret = 0; |
998 | |
999 | out: |
1000 | return ret; |
1001 | } |
1002 | EXPORT_SYMBOL(clk_set_rate); |
1003 | |
1004 | int clk_enable(struct clk *clk) |
1005 | { |
1006 | unsigned long clocks_flags; |
1007 | |
1008 | if (unlikely(!clk_good(clk))) |
1009 | return -EINVAL; |
1010 | |
1011 | if (clk->parent) |
1012 | clk_enable(clk->parent); |
1013 | |
1014 | spin_lock_irqsave(&clocks_lock, clocks_flags); |
1015 | |
1016 | clk->usage++; |
1017 | if (clk->ops && clk->ops->enable) |
1018 | clk->ops->enable(clk); |
1019 | |
1020 | spin_unlock_irqrestore(&clocks_lock, clocks_flags); |
1021 | return 0; |
1022 | } |
1023 | EXPORT_SYMBOL(clk_enable); |
1024 | |
1025 | static void local_clk_disable(struct clk *clk) |
1026 | { |
1027 | if (unlikely(!clk_good(clk))) |
1028 | return; |
1029 | |
1030 | if (clk->usage == 0 && clk->ops->disable) |
1031 | clk->ops->disable(clk); |
1032 | |
1033 | if (clk->parent) |
1034 | local_clk_disable(clk->parent); |
1035 | } |
1036 | |
1037 | void clk_disable(struct clk *clk) |
1038 | { |
1039 | unsigned long clocks_flags; |
1040 | |
1041 | if (unlikely(!clk_good(clk))) |
1042 | return; |
1043 | |
1044 | spin_lock_irqsave(&clocks_lock, clocks_flags); |
1045 | |
1046 | if ((--clk->usage) == 0 && clk->ops->disable) |
1047 | clk->ops->disable(clk); |
1048 | |
1049 | spin_unlock_irqrestore(&clocks_lock, clocks_flags); |
1050 | if (clk->parent) |
1051 | clk_disable(clk->parent); |
1052 | } |
1053 | EXPORT_SYMBOL(clk_disable); |
1054 | |
1055 | /* Some additional API */ |
1056 | int clk_set_parent(struct clk *clk, struct clk *parent) |
1057 | { |
1058 | int ret = -ENODEV; |
1059 | unsigned long clocks_flags; |
1060 | |
1061 | if (unlikely(!clk_good(clk))) |
1062 | goto out; |
1063 | |
1064 | if (!clk->ops->set_parent) |
1065 | goto out; |
1066 | |
1067 | spin_lock_irqsave(&clocks_lock, clocks_flags); |
1068 | |
1069 | ret = clk->ops->set_parent(clk, parent); |
1070 | if (!ret) { |
1071 | /* disable if usage count is 0 */ |
1072 | local_clk_disable(parent); |
1073 | |
1074 | parent->usage += clk->usage; |
1075 | clk->parent->usage -= clk->usage; |
1076 | |
1077 | /* disable if new usage count is 0 */ |
1078 | local_clk_disable(clk->parent); |
1079 | |
1080 | clk->parent = parent; |
1081 | } |
1082 | spin_unlock_irqrestore(&clocks_lock, clocks_flags); |
1083 | |
1084 | out: |
1085 | return ret; |
1086 | } |
1087 | EXPORT_SYMBOL(clk_set_parent); |
1088 | |
1089 | struct clk *clk_get_parent(struct clk *clk) |
1090 | { |
1091 | if (unlikely(!clk_good(clk))) |
1092 | return NULL; |
1093 | return clk->parent; |
1094 | } |
1095 | EXPORT_SYMBOL(clk_get_parent); |
1096 | |
1097 | static int __init clk_init(void) |
1098 | { |
1099 | struct clk_lookup *cl; |
1100 | struct clk_ops *ops; |
1101 | |
1102 | spin_lock_init(&clocks_lock); |
1103 | |
1104 | for (cl = onchip_clks; cl < onchip_clks + ARRAY_SIZE(onchip_clks); |
1105 | cl++) { |
1106 | if (cl->clk->flags & ENABLED) |
1107 | clk_enable(cl->clk); |
1108 | else |
1109 | local_clk_disable(cl->clk); |
1110 | |
1111 | ops = cl->clk->ops; |
1112 | |
1113 | if ((cl->clk->flags & NEEDS_INITIALIZATION) && |
1114 | ops && ops->set_rate) |
1115 | ops->set_rate(cl->clk, cl->clk->rate); |
1116 | |
1117 | if (cl->clk->flags & FIXED_RATE) { |
1118 | if (cl->clk->flags & RATE_PROPAGATES) |
1119 | propagate_rate(cl->clk); |
1120 | } else { |
1121 | if (ops && ops->get_rate) |
1122 | ops->get_rate(cl->clk); |
1123 | } |
1124 | |
1125 | if (cl->clk->flags & NEEDS_SET_PARENT) { |
1126 | if (ops && ops->set_parent) |
1127 | ops->set_parent(cl->clk, cl->clk->parent); |
1128 | } |
5cccd37e |
1129 | } |
0a0300dc |
1130 | clkdev_add_table(onchip_clks, ARRAY_SIZE(onchip_clks)); |
5cccd37e |
1131 | return 0; |
1132 | } |
1133 | |
1134 | arch_initcall(clk_init); |