blob: a4a3819c96cbf2777da665a5ccef10323f7caab5 [file] [log] [blame]
Vitaly Wool78818e42006-05-16 11:54:37 +01001/*
2 * arch/arm/mach-pnx4008/clock.c
3 *
4 * Clock control driver for PNX4008
5 *
6 * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
7 * Generic clock management functions are partially based on:
8 * linux/arch/arm/mach-omap/clock.c
9 *
10 * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under
11 * the terms of the GNU General Public License version 2. This program
12 * is licensed "as is" without any warranty of any kind, whether express
13 * or implied.
14 */
15
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/list.h>
19#include <linux/errno.h>
20#include <linux/device.h>
21#include <linux/err.h>
22#include <linux/delay.h>
Russell Kingfced80c2008-09-06 12:10:45 +010023#include <linux/io.h>
Jean-Christop PLAGNIOL-VILLARD6d803ba2010-11-17 10:04:33 +010024#include <linux/clkdev.h>
Vitaly Wool78818e42006-05-16 11:54:37 +010025
Russell King6985a5a2009-11-20 10:32:41 +000026#include <mach/hardware.h>
Russell Kinga09e64f2008-08-05 16:14:15 +010027#include <mach/clock.h>
Vitaly Wool78818e42006-05-16 11:54:37 +010028#include "clock.h"
29
30/*forward declaration*/
31static struct clk per_ck;
32static struct clk hclk_ck;
33static struct clk ck_1MHz;
34static struct clk ck_13MHz;
35static struct clk ck_pll1;
36static int local_set_rate(struct clk *clk, u32 rate);
37
38static inline void clock_lock(void)
39{
40 local_irq_disable();
41}
42
43static inline void clock_unlock(void)
44{
45 local_irq_enable();
46}
47
48static void propagate_rate(struct clk *clk)
49{
50 struct clk *tmp_clk;
51
52 tmp_clk = clk;
53 while (tmp_clk->propagate_next) {
54 tmp_clk = tmp_clk->propagate_next;
55 local_set_rate(tmp_clk, tmp_clk->user_rate);
56 }
57}
58
Russell King0c452df2009-11-20 11:28:59 +000059static void clk_reg_disable(struct clk *clk)
Vitaly Wool78818e42006-05-16 11:54:37 +010060{
61 if (clk->enable_reg)
62 __raw_writel(__raw_readl(clk->enable_reg) &
63 ~(1 << clk->enable_shift), clk->enable_reg);
64}
65
Russell King0c452df2009-11-20 11:28:59 +000066static int clk_reg_enable(struct clk *clk)
Vitaly Wool78818e42006-05-16 11:54:37 +010067{
68 if (clk->enable_reg)
69 __raw_writel(__raw_readl(clk->enable_reg) |
70 (1 << clk->enable_shift), clk->enable_reg);
Russell King0c452df2009-11-20 11:28:59 +000071 return 0;
Vitaly Wool78818e42006-05-16 11:54:37 +010072}
73
74static inline void clk_reg_disable1(struct clk *clk)
75{
76 if (clk->enable_reg1)
77 __raw_writel(__raw_readl(clk->enable_reg1) &
78 ~(1 << clk->enable_shift1), clk->enable_reg1);
79}
80
81static inline void clk_reg_enable1(struct clk *clk)
82{
83 if (clk->enable_reg1)
84 __raw_writel(__raw_readl(clk->enable_reg1) |
85 (1 << clk->enable_shift1), clk->enable_reg1);
86}
87
88static int clk_wait_for_pll_lock(struct clk *clk)
89{
90 int i;
91 i = 0;
92 while (i++ < 0xFFF && !(__raw_readl(clk->scale_reg) & 1)) ; /*wait for PLL to lock */
93
94 if (!(__raw_readl(clk->scale_reg) & 1)) {
95 printk(KERN_ERR
96 "%s ERROR: failed to lock, scale reg data: %x\n",
97 clk->name, __raw_readl(clk->scale_reg));
98 return -1;
99 }
100 return 0;
101}
102
103static int switch_to_dirty_13mhz(struct clk *clk)
104{
105 int i;
106 int ret;
107 u32 tmp_reg;
108
109 ret = 0;
110
111 if (!clk->rate)
112 clk_reg_enable1(clk);
113
114 tmp_reg = __raw_readl(clk->parent_switch_reg);
115 /*if 13Mhz clock selected, select 13'MHz (dirty) source from OSC */
116 if (!(tmp_reg & 1)) {
117 tmp_reg |= (1 << 1); /* Trigger switch to 13'MHz (dirty) clock */
118 __raw_writel(tmp_reg, clk->parent_switch_reg);
119 i = 0;
120 while (i++ < 0xFFF && !(__raw_readl(clk->parent_switch_reg) & 1)) ; /*wait for 13'MHz selection status */
121
122 if (!(__raw_readl(clk->parent_switch_reg) & 1)) {
123 printk(KERN_ERR
124 "%s ERROR: failed to select 13'MHz, parent sw reg data: %x\n",
125 clk->name, __raw_readl(clk->parent_switch_reg));
126 ret = -1;
127 }
128 }
129
130 if (!clk->rate)
131 clk_reg_disable1(clk);
132
133 return ret;
134}
135
136static int switch_to_clean_13mhz(struct clk *clk)
137{
138 int i;
139 int ret;
140 u32 tmp_reg;
141
142 ret = 0;
143
144 if (!clk->rate)
145 clk_reg_enable1(clk);
146
147 tmp_reg = __raw_readl(clk->parent_switch_reg);
148 /*if 13'Mhz clock selected, select 13MHz (clean) source from OSC */
149 if (tmp_reg & 1) {
150 tmp_reg &= ~(1 << 1); /* Trigger switch to 13MHz (clean) clock */
151 __raw_writel(tmp_reg, clk->parent_switch_reg);
152 i = 0;
153 while (i++ < 0xFFF && (__raw_readl(clk->parent_switch_reg) & 1)) ; /*wait for 13MHz selection status */
154
155 if (__raw_readl(clk->parent_switch_reg) & 1) {
156 printk(KERN_ERR
157 "%s ERROR: failed to select 13MHz, parent sw reg data: %x\n",
158 clk->name, __raw_readl(clk->parent_switch_reg));
159 ret = -1;
160 }
161 }
162
163 if (!clk->rate)
164 clk_reg_disable1(clk);
165
166 return ret;
167}
168
169static int set_13MHz_parent(struct clk *clk, struct clk *parent)
170{
171 int ret = -EINVAL;
172
173 if (parent == &ck_13MHz)
174 ret = switch_to_clean_13mhz(clk);
175 else if (parent == &ck_pll1)
176 ret = switch_to_dirty_13mhz(clk);
177
178 return ret;
179}
180
181#define PLL160_MIN_FCCO 156000
182#define PLL160_MAX_FCCO 320000
183
184/*
185 * Calculate pll160 settings.
186 * Possible input: up to 320MHz with step of clk->parent->rate.
187 * In PNX4008 parent rate for pll160s may be either 1 or 13MHz.
188 * Ignored paths: "feedback" (bit 13 set), "div-by-N".
189 * Setting ARM PLL4 rate to 0 will put CPU into direct run mode.
190 * Setting PLL5 and PLL3 rate to 0 will disable USB and DSP clock input.
191 * Please refer to PNX4008 IC manual for details.
192 */
193
194static int pll160_set_rate(struct clk *clk, u32 rate)
195{
196 u32 tmp_reg, tmp_m, tmp_2p, i;
197 u32 parent_rate;
198 int ret = -EINVAL;
199
200 parent_rate = clk->parent->rate;
201
202 if (!parent_rate)
203 goto out;
204
205 /* set direct run for ARM or disable output for others */
206 clk_reg_disable(clk);
207
208 /* disable source input as well (ignored for ARM) */
209 clk_reg_disable1(clk);
210
211 tmp_reg = __raw_readl(clk->scale_reg);
212 tmp_reg &= ~0x1ffff; /*clear all settings, power down */
213 __raw_writel(tmp_reg, clk->scale_reg);
214
215 rate -= rate % parent_rate; /*round down the input */
216
217 if (rate > PLL160_MAX_FCCO)
218 rate = PLL160_MAX_FCCO;
219
220 if (!rate) {
221 clk->rate = 0;
222 ret = 0;
223 goto out;
224 }
225
226 clk_reg_enable1(clk);
227 tmp_reg = __raw_readl(clk->scale_reg);
228
229 if (rate == parent_rate) {
230 /*enter direct bypass mode */
231 tmp_reg |= ((1 << 14) | (1 << 15));
232 __raw_writel(tmp_reg, clk->scale_reg);
233 clk->rate = parent_rate;
234 clk_reg_enable(clk);
235 ret = 0;
236 goto out;
237 }
238
239 i = 0;
240 for (tmp_2p = 1; tmp_2p < 16; tmp_2p <<= 1) {
241 if (rate * tmp_2p >= PLL160_MIN_FCCO)
242 break;
243 i++;
244 }
245
246 if (tmp_2p > 1)
247 tmp_reg |= ((i - 1) << 11);
248 else
249 tmp_reg |= (1 << 14); /*direct mode, no divide */
250
251 tmp_m = rate * tmp_2p;
252 tmp_m /= parent_rate;
253
254 tmp_reg |= (tmp_m - 1) << 1; /*calculate M */
255 tmp_reg |= (1 << 16); /*power up PLL */
256 __raw_writel(tmp_reg, clk->scale_reg);
257
258 if (clk_wait_for_pll_lock(clk) < 0) {
259 clk_reg_disable(clk);
260 clk_reg_disable1(clk);
261
262 tmp_reg = __raw_readl(clk->scale_reg);
263 tmp_reg &= ~0x1ffff; /*clear all settings, power down */
264 __raw_writel(tmp_reg, clk->scale_reg);
265 clk->rate = 0;
266 ret = -EFAULT;
267 goto out;
268 }
269
270 clk->rate = (tmp_m * parent_rate) / tmp_2p;
271
272 if (clk->flags & RATE_PROPAGATES)
273 propagate_rate(clk);
274
275 clk_reg_enable(clk);
276 ret = 0;
277
278out:
279 return ret;
280}
281
282/*configure PER_CLK*/
283static int per_clk_set_rate(struct clk *clk, u32 rate)
284{
285 u32 tmp;
286
287 tmp = __raw_readl(clk->scale_reg);
288 tmp &= ~(0x1f << 2);
289 tmp |= ((clk->parent->rate / clk->rate) - 1) << 2;
290 __raw_writel(tmp, clk->scale_reg);
291 clk->rate = rate;
292 return 0;
293}
294
295/*configure HCLK*/
296static int hclk_set_rate(struct clk *clk, u32 rate)
297{
298 u32 tmp;
299 tmp = __raw_readl(clk->scale_reg);
300 tmp = tmp & ~0x3;
301 switch (rate) {
302 case 1:
303 break;
304 case 2:
305 tmp |= 1;
306 break;
307 case 4:
308 tmp |= 2;
309 break;
310 }
311
312 __raw_writel(tmp, clk->scale_reg);
313 clk->rate = rate;
314 return 0;
315}
316
317static u32 hclk_round_rate(struct clk *clk, u32 rate)
318{
319 switch (rate) {
320 case 1:
321 case 4:
322 return rate;
323 }
324 return 2;
325}
326
327static u32 per_clk_round_rate(struct clk *clk, u32 rate)
328{
329 return CLK_RATE_13MHZ;
330}
331
332static int on_off_set_rate(struct clk *clk, u32 rate)
333{
334 if (rate) {
335 clk_reg_enable(clk);
336 clk->rate = 1;
337 } else {
338 clk_reg_disable(clk);
339 clk->rate = 0;
340 }
341 return 0;
342}
343
344static int on_off_inv_set_rate(struct clk *clk, u32 rate)
345{
346 if (rate) {
347 clk_reg_disable(clk); /*enable bit is inverted */
348 clk->rate = 1;
349 } else {
350 clk_reg_enable(clk);
351 clk->rate = 0;
352 }
353 return 0;
354}
355
356static u32 on_off_round_rate(struct clk *clk, u32 rate)
357{
358 return (rate ? 1 : 0);
359}
360
361static u32 pll4_round_rate(struct clk *clk, u32 rate)
362{
363 if (rate > CLK_RATE_208MHZ)
364 rate = CLK_RATE_208MHZ;
365 if (rate == CLK_RATE_208MHZ && hclk_ck.user_rate == 1)
366 rate = CLK_RATE_208MHZ - CLK_RATE_13MHZ;
367 return (rate - (rate % (hclk_ck.user_rate * CLK_RATE_13MHZ)));
368}
369
370static u32 pll3_round_rate(struct clk *clk, u32 rate)
371{
372 if (rate > CLK_RATE_208MHZ)
373 rate = CLK_RATE_208MHZ;
374 return (rate - rate % CLK_RATE_13MHZ);
375}
376
377static u32 pll5_round_rate(struct clk *clk, u32 rate)
378{
379 return (rate ? CLK_RATE_48MHZ : 0);
380}
381
382static u32 ck_13MHz_round_rate(struct clk *clk, u32 rate)
383{
384 return (rate ? CLK_RATE_13MHZ : 0);
385}
386
387static int ck_13MHz_set_rate(struct clk *clk, u32 rate)
388{
389 if (rate) {
390 clk_reg_disable(clk); /*enable bit is inverted */
391 udelay(500);
392 clk->rate = CLK_RATE_13MHZ;
393 ck_1MHz.rate = CLK_RATE_1MHZ;
394 } else {
395 clk_reg_enable(clk);
396 clk->rate = 0;
397 ck_1MHz.rate = 0;
398 }
399 return 0;
400}
401
402static int pll1_set_rate(struct clk *clk, u32 rate)
403{
404#if 0 /* doesn't work on some boards, probably a HW BUG */
405 if (rate) {
406 clk_reg_disable(clk); /*enable bit is inverted */
407 if (!clk_wait_for_pll_lock(clk)) {
408 clk->rate = CLK_RATE_13MHZ;
409 } else {
410 clk_reg_enable(clk);
411 clk->rate = 0;
412 }
413
414 } else {
415 clk_reg_enable(clk);
416 clk->rate = 0;
417 }
418#endif
419 return 0;
420}
421
422/* Clock sources */
423
424static struct clk osc_13MHz = {
425 .name = "osc_13MHz",
426 .flags = FIXED_RATE,
427 .rate = CLK_RATE_13MHZ,
428};
429
430static struct clk ck_13MHz = {
431 .name = "ck_13MHz",
432 .parent = &osc_13MHz,
433 .flags = NEEDS_INITIALIZATION,
434 .round_rate = &ck_13MHz_round_rate,
435 .set_rate = &ck_13MHz_set_rate,
436 .enable_reg = OSC13CTRL_REG,
437 .enable_shift = 0,
438 .rate = CLK_RATE_13MHZ,
439};
440
441static struct clk osc_32KHz = {
442 .name = "osc_32KHz",
443 .flags = FIXED_RATE,
444 .rate = CLK_RATE_32KHZ,
445};
446
447/*attached to PLL5*/
448static struct clk ck_1MHz = {
449 .name = "ck_1MHz",
450 .flags = FIXED_RATE | PARENT_SET_RATE,
451 .parent = &ck_13MHz,
452};
453
454/* PLL1 (397) - provides 13' MHz clock */
455static struct clk ck_pll1 = {
456 .name = "ck_pll1",
457 .parent = &osc_32KHz,
458 .flags = NEEDS_INITIALIZATION,
459 .round_rate = &ck_13MHz_round_rate,
460 .set_rate = &pll1_set_rate,
461 .enable_reg = PLLCTRL_REG,
462 .enable_shift = 1,
463 .scale_reg = PLLCTRL_REG,
464 .rate = CLK_RATE_13MHZ,
465};
466
467/* CPU/Bus PLL */
468static struct clk ck_pll4 = {
469 .name = "ck_pll4",
470 .parent = &ck_pll1,
471 .flags = RATE_PROPAGATES | NEEDS_INITIALIZATION,
472 .propagate_next = &per_ck,
473 .round_rate = &pll4_round_rate,
474 .set_rate = &pll160_set_rate,
475 .rate = CLK_RATE_208MHZ,
476 .scale_reg = HCLKPLLCTRL_REG,
477 .enable_reg = PWRCTRL_REG,
478 .enable_shift = 2,
479 .parent_switch_reg = SYSCLKCTRL_REG,
480 .set_parent = &set_13MHz_parent,
481};
482
483/* USB PLL */
484static struct clk ck_pll5 = {
485 .name = "ck_pll5",
486 .parent = &ck_1MHz,
487 .flags = NEEDS_INITIALIZATION,
488 .round_rate = &pll5_round_rate,
489 .set_rate = &pll160_set_rate,
490 .scale_reg = USBCTRL_REG,
491 .enable_reg = USBCTRL_REG,
492 .enable_shift = 18,
493 .enable_reg1 = USBCTRL_REG,
494 .enable_shift1 = 17,
495};
496
497/* XPERTTeak DSP PLL */
498static struct clk ck_pll3 = {
499 .name = "ck_pll3",
500 .parent = &ck_pll1,
501 .flags = NEEDS_INITIALIZATION,
502 .round_rate = &pll3_round_rate,
503 .set_rate = &pll160_set_rate,
504 .scale_reg = DSPPLLCTRL_REG,
505 .enable_reg = DSPCLKCTRL_REG,
506 .enable_shift = 3,
507 .enable_reg1 = DSPCLKCTRL_REG,
508 .enable_shift1 = 2,
509 .parent_switch_reg = DSPCLKCTRL_REG,
510 .set_parent = &set_13MHz_parent,
511};
512
513static struct clk hclk_ck = {
514 .name = "hclk_ck",
515 .parent = &ck_pll4,
516 .flags = PARENT_SET_RATE,
517 .set_rate = &hclk_set_rate,
518 .round_rate = &hclk_round_rate,
519 .scale_reg = HCLKDIVCTRL_REG,
520 .rate = 2,
521 .user_rate = 2,
522};
523
524static struct clk per_ck = {
525 .name = "per_ck",
526 .parent = &ck_pll4,
527 .flags = FIXED_RATE,
528 .propagate_next = &hclk_ck,
529 .set_rate = &per_clk_set_rate,
530 .round_rate = &per_clk_round_rate,
531 .scale_reg = HCLKDIVCTRL_REG,
532 .rate = CLK_RATE_13MHZ,
533 .user_rate = CLK_RATE_13MHZ,
534};
535
536static struct clk m2hclk_ck = {
537 .name = "m2hclk_ck",
538 .parent = &hclk_ck,
539 .flags = NEEDS_INITIALIZATION,
540 .round_rate = &on_off_round_rate,
541 .set_rate = &on_off_inv_set_rate,
542 .rate = 1,
543 .enable_shift = 6,
544 .enable_reg = PWRCTRL_REG,
545};
546
547static struct clk vfp9_ck = {
548 .name = "vfp9_ck",
549 .parent = &ck_pll4,
550 .flags = NEEDS_INITIALIZATION,
551 .round_rate = &on_off_round_rate,
552 .set_rate = &on_off_set_rate,
553 .rate = 1,
554 .enable_shift = 4,
555 .enable_reg = VFP9CLKCTRL_REG,
556};
557
558static struct clk keyscan_ck = {
559 .name = "keyscan_ck",
560 .parent = &osc_32KHz,
561 .flags = NEEDS_INITIALIZATION,
562 .round_rate = &on_off_round_rate,
563 .set_rate = &on_off_set_rate,
564 .enable_shift = 0,
565 .enable_reg = KEYCLKCTRL_REG,
566};
567
568static struct clk touch_ck = {
569 .name = "touch_ck",
570 .parent = &osc_32KHz,
571 .flags = NEEDS_INITIALIZATION,
572 .round_rate = &on_off_round_rate,
573 .set_rate = &on_off_set_rate,
574 .enable_shift = 0,
575 .enable_reg = TSCLKCTRL_REG,
576};
577
578static struct clk pwm1_ck = {
579 .name = "pwm1_ck",
580 .parent = &osc_32KHz,
581 .flags = NEEDS_INITIALIZATION,
582 .round_rate = &on_off_round_rate,
583 .set_rate = &on_off_set_rate,
584 .enable_shift = 0,
585 .enable_reg = PWMCLKCTRL_REG,
586};
587
588static struct clk pwm2_ck = {
589 .name = "pwm2_ck",
590 .parent = &osc_32KHz,
591 .flags = NEEDS_INITIALIZATION,
592 .round_rate = &on_off_round_rate,
593 .set_rate = &on_off_set_rate,
594 .enable_shift = 2,
595 .enable_reg = PWMCLKCTRL_REG,
596};
597
598static struct clk jpeg_ck = {
599 .name = "jpeg_ck",
600 .parent = &hclk_ck,
601 .flags = NEEDS_INITIALIZATION,
602 .round_rate = &on_off_round_rate,
603 .set_rate = &on_off_set_rate,
604 .enable_shift = 0,
605 .enable_reg = JPEGCLKCTRL_REG,
606};
607
608static struct clk ms_ck = {
609 .name = "ms_ck",
610 .parent = &ck_pll4,
611 .flags = NEEDS_INITIALIZATION,
612 .round_rate = &on_off_round_rate,
613 .set_rate = &on_off_set_rate,
614 .enable_shift = 5,
615 .enable_reg = MSCTRL_REG,
616};
617
618static struct clk dum_ck = {
619 .name = "dum_ck",
620 .parent = &hclk_ck,
621 .flags = NEEDS_INITIALIZATION,
622 .round_rate = &on_off_round_rate,
623 .set_rate = &on_off_set_rate,
624 .enable_shift = 0,
625 .enable_reg = DUMCLKCTRL_REG,
626};
627
628static struct clk flash_ck = {
629 .name = "flash_ck",
630 .parent = &hclk_ck,
631 .round_rate = &on_off_round_rate,
632 .set_rate = &on_off_set_rate,
633 .enable_shift = 1, /* Only MLC clock supported */
634 .enable_reg = FLASHCLKCTRL_REG,
635};
636
637static struct clk i2c0_ck = {
638 .name = "i2c0_ck",
639 .parent = &per_ck,
Russell King6fff3da2009-11-20 12:46:07 +0000640 .flags = NEEDS_INITIALIZATION | FIXED_RATE,
Vitaly Wool78818e42006-05-16 11:54:37 +0100641 .enable_shift = 0,
642 .enable_reg = I2CCLKCTRL_REG,
Russell King6fff3da2009-11-20 12:46:07 +0000643 .rate = 13000000,
Russell Kingebdbbf22009-11-20 11:44:46 +0000644 .enable = clk_reg_enable,
645 .disable = clk_reg_disable,
Vitaly Wool78818e42006-05-16 11:54:37 +0100646};
647
648static struct clk i2c1_ck = {
649 .name = "i2c1_ck",
650 .parent = &per_ck,
Russell King6fff3da2009-11-20 12:46:07 +0000651 .flags = NEEDS_INITIALIZATION | FIXED_RATE,
Vitaly Wool78818e42006-05-16 11:54:37 +0100652 .enable_shift = 1,
653 .enable_reg = I2CCLKCTRL_REG,
Russell King6fff3da2009-11-20 12:46:07 +0000654 .rate = 13000000,
Russell Kingebdbbf22009-11-20 11:44:46 +0000655 .enable = clk_reg_enable,
656 .disable = clk_reg_disable,
Vitaly Wool78818e42006-05-16 11:54:37 +0100657};
658
659static struct clk i2c2_ck = {
660 .name = "i2c2_ck",
661 .parent = &per_ck,
Russell King6fff3da2009-11-20 12:46:07 +0000662 .flags = NEEDS_INITIALIZATION | FIXED_RATE,
Vitaly Wool78818e42006-05-16 11:54:37 +0100663 .enable_shift = 2,
664 .enable_reg = USB_OTG_CLKCTRL_REG,
Russell King6fff3da2009-11-20 12:46:07 +0000665 .rate = 13000000,
Russell Kingebdbbf22009-11-20 11:44:46 +0000666 .enable = clk_reg_enable,
667 .disable = clk_reg_disable,
Vitaly Wool78818e42006-05-16 11:54:37 +0100668};
669
670static struct clk spi0_ck = {
671 .name = "spi0_ck",
672 .parent = &hclk_ck,
673 .flags = NEEDS_INITIALIZATION,
674 .round_rate = &on_off_round_rate,
675 .set_rate = &on_off_set_rate,
676 .enable_shift = 0,
677 .enable_reg = SPICTRL_REG,
678};
679
680static struct clk spi1_ck = {
681 .name = "spi1_ck",
682 .parent = &hclk_ck,
683 .flags = NEEDS_INITIALIZATION,
684 .round_rate = &on_off_round_rate,
685 .set_rate = &on_off_set_rate,
686 .enable_shift = 4,
687 .enable_reg = SPICTRL_REG,
688};
689
690static struct clk dma_ck = {
691 .name = "dma_ck",
692 .parent = &hclk_ck,
693 .round_rate = &on_off_round_rate,
694 .set_rate = &on_off_set_rate,
695 .enable_shift = 0,
696 .enable_reg = DMACLKCTRL_REG,
697};
698
699static struct clk uart3_ck = {
700 .name = "uart3_ck",
701 .parent = &per_ck,
702 .flags = NEEDS_INITIALIZATION,
703 .round_rate = &on_off_round_rate,
704 .set_rate = &on_off_set_rate,
705 .rate = 1,
706 .enable_shift = 0,
707 .enable_reg = UARTCLKCTRL_REG,
708};
709
710static struct clk uart4_ck = {
711 .name = "uart4_ck",
712 .parent = &per_ck,
713 .flags = NEEDS_INITIALIZATION,
714 .round_rate = &on_off_round_rate,
715 .set_rate = &on_off_set_rate,
716 .enable_shift = 1,
717 .enable_reg = UARTCLKCTRL_REG,
718};
719
720static struct clk uart5_ck = {
721 .name = "uart5_ck",
722 .parent = &per_ck,
723 .flags = NEEDS_INITIALIZATION,
724 .round_rate = &on_off_round_rate,
725 .set_rate = &on_off_set_rate,
726 .rate = 1,
727 .enable_shift = 2,
728 .enable_reg = UARTCLKCTRL_REG,
729};
730
731static struct clk uart6_ck = {
732 .name = "uart6_ck",
733 .parent = &per_ck,
734 .flags = NEEDS_INITIALIZATION,
735 .round_rate = &on_off_round_rate,
736 .set_rate = &on_off_set_rate,
737 .enable_shift = 3,
738 .enable_reg = UARTCLKCTRL_REG,
739};
740
Vitaly Wool9325fa362006-06-26 19:31:49 +0400741static struct clk wdt_ck = {
742 .name = "wdt_ck",
743 .parent = &per_ck,
744 .flags = NEEDS_INITIALIZATION,
Vitaly Wool9325fa362006-06-26 19:31:49 +0400745 .enable_shift = 0,
746 .enable_reg = TIMCLKCTRL_REG,
Russell King24fd1ed2009-11-20 13:04:14 +0000747 .enable = clk_reg_enable,
748 .disable = clk_reg_disable,
Vitaly Wool9325fa362006-06-26 19:31:49 +0400749};
750
Vitaly Wool78818e42006-05-16 11:54:37 +0100751/* These clocks are visible outside this module
752 * and can be initialized
753 */
Russell King6985a5a2009-11-20 10:32:41 +0000754static struct clk *onchip_clks[] __initdata = {
Vitaly Wool78818e42006-05-16 11:54:37 +0100755 &ck_13MHz,
756 &ck_pll1,
757 &ck_pll4,
758 &ck_pll5,
759 &ck_pll3,
760 &vfp9_ck,
761 &m2hclk_ck,
762 &hclk_ck,
763 &dma_ck,
764 &flash_ck,
765 &dum_ck,
766 &keyscan_ck,
767 &pwm1_ck,
768 &pwm2_ck,
769 &jpeg_ck,
770 &ms_ck,
771 &touch_ck,
772 &i2c0_ck,
773 &i2c1_ck,
774 &i2c2_ck,
775 &spi0_ck,
776 &spi1_ck,
777 &uart3_ck,
778 &uart4_ck,
779 &uart5_ck,
780 &uart6_ck,
Vitaly Wool9325fa362006-06-26 19:31:49 +0400781 &wdt_ck,
Vitaly Wool78818e42006-05-16 11:54:37 +0100782};
783
Russell King6985a5a2009-11-20 10:32:41 +0000784static struct clk_lookup onchip_clkreg[] = {
785 { .clk = &ck_13MHz, .con_id = "ck_13MHz" },
786 { .clk = &ck_pll1, .con_id = "ck_pll1" },
787 { .clk = &ck_pll4, .con_id = "ck_pll4" },
788 { .clk = &ck_pll5, .con_id = "ck_pll5" },
789 { .clk = &ck_pll3, .con_id = "ck_pll3" },
790 { .clk = &vfp9_ck, .con_id = "vfp9_ck" },
791 { .clk = &m2hclk_ck, .con_id = "m2hclk_ck" },
792 { .clk = &hclk_ck, .con_id = "hclk_ck" },
793 { .clk = &dma_ck, .con_id = "dma_ck" },
794 { .clk = &flash_ck, .con_id = "flash_ck" },
795 { .clk = &dum_ck, .con_id = "dum_ck" },
796 { .clk = &keyscan_ck, .con_id = "keyscan_ck" },
797 { .clk = &pwm1_ck, .con_id = "pwm1_ck" },
798 { .clk = &pwm2_ck, .con_id = "pwm2_ck" },
799 { .clk = &jpeg_ck, .con_id = "jpeg_ck" },
800 { .clk = &ms_ck, .con_id = "ms_ck" },
801 { .clk = &touch_ck, .con_id = "touch_ck" },
Russell Kingbba2be42009-11-20 10:46:24 +0000802 { .clk = &i2c0_ck, .dev_id = "pnx-i2c.0" },
803 { .clk = &i2c1_ck, .dev_id = "pnx-i2c.1" },
804 { .clk = &i2c2_ck, .dev_id = "pnx-i2c.2" },
Russell King6985a5a2009-11-20 10:32:41 +0000805 { .clk = &spi0_ck, .con_id = "spi0_ck" },
806 { .clk = &spi1_ck, .con_id = "spi1_ck" },
807 { .clk = &uart3_ck, .con_id = "uart3_ck" },
808 { .clk = &uart4_ck, .con_id = "uart4_ck" },
809 { .clk = &uart5_ck, .con_id = "uart5_ck" },
810 { .clk = &uart6_ck, .con_id = "uart6_ck" },
Russell King9bb787f2009-11-20 13:07:28 +0000811 { .clk = &wdt_ck, .dev_id = "pnx4008-watchdog" },
Russell King6985a5a2009-11-20 10:32:41 +0000812};
813
Russell King5413f742009-11-20 11:25:44 +0000814static void local_clk_disable(struct clk *clk)
815{
816 if (WARN_ON(clk->usecount == 0))
817 return;
818
819 if (!(--clk->usecount)) {
Russell King0c452df2009-11-20 11:28:59 +0000820 if (clk->disable)
821 clk->disable(clk);
822 else if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate)
Russell King5413f742009-11-20 11:25:44 +0000823 clk->set_rate(clk, 0);
824 if (clk->parent)
825 local_clk_disable(clk->parent);
826 }
827}
828
Vitaly Woole9931b52006-06-22 10:26:20 +0100829static int local_clk_enable(struct clk *clk)
830{
831 int ret = 0;
832
Russell King5413f742009-11-20 11:25:44 +0000833 if (clk->usecount == 0) {
834 if (clk->parent) {
835 ret = local_clk_enable(clk->parent);
836 if (ret != 0)
837 goto out;
838 }
Vitaly Woole9931b52006-06-22 10:26:20 +0100839
Russell King0c452df2009-11-20 11:28:59 +0000840 if (clk->enable)
841 ret = clk->enable(clk);
842 else if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate
843 && clk->user_rate)
Russell King5413f742009-11-20 11:25:44 +0000844 ret = clk->set_rate(clk, clk->user_rate);
Vitaly Woole9931b52006-06-22 10:26:20 +0100845
Russell King5413f742009-11-20 11:25:44 +0000846 if (ret != 0 && clk->parent) {
847 local_clk_disable(clk->parent);
Vitaly Woole9931b52006-06-22 10:26:20 +0100848 goto out;
849 }
850
Russell King5413f742009-11-20 11:25:44 +0000851 clk->usecount++;
Vitaly Woole9931b52006-06-22 10:26:20 +0100852 }
853out:
854 return ret;
855}
856
Vitaly Wool78818e42006-05-16 11:54:37 +0100857static int local_set_rate(struct clk *clk, u32 rate)
858{
859 int ret = -EINVAL;
860 if (clk->set_rate) {
861
862 if (clk->user_rate == clk->rate && clk->parent->rate) {
863 /* if clock enabled or rate not set */
864 clk->user_rate = clk->round_rate(clk, rate);
865 ret = clk->set_rate(clk, clk->user_rate);
866 } else
867 clk->user_rate = clk->round_rate(clk, rate);
868 ret = 0;
869 }
870 return ret;
871}
872
873int clk_set_rate(struct clk *clk, unsigned long rate)
874{
875 int ret = -EINVAL;
876
877 if (clk->flags & FIXED_RATE)
878 goto out;
879
880 clock_lock();
881 if ((clk->flags & PARENT_SET_RATE) && clk->parent) {
882
883 clk->user_rate = clk->round_rate(clk, rate);
884 /* parent clock needs to be refreshed
885 for the setting to take effect */
886 } else {
887 ret = local_set_rate(clk, rate);
888 }
889 ret = 0;
890 clock_unlock();
891
892out:
893 return ret;
894}
895
896EXPORT_SYMBOL(clk_set_rate);
897
Vitaly Wool78818e42006-05-16 11:54:37 +0100898unsigned long clk_get_rate(struct clk *clk)
899{
900 unsigned long ret;
901 clock_lock();
902 ret = clk->rate;
903 clock_unlock();
904 return ret;
905}
906EXPORT_SYMBOL(clk_get_rate);
907
Vitaly Wool78818e42006-05-16 11:54:37 +0100908int clk_enable(struct clk *clk)
909{
Russell King5413f742009-11-20 11:25:44 +0000910 int ret;
Vitaly Wool78818e42006-05-16 11:54:37 +0100911
912 clock_lock();
Russell King5413f742009-11-20 11:25:44 +0000913 ret = local_clk_enable(clk);
Vitaly Wool78818e42006-05-16 11:54:37 +0100914 clock_unlock();
915 return ret;
916}
917
918EXPORT_SYMBOL(clk_enable);
919
920void clk_disable(struct clk *clk)
921{
922 clock_lock();
Russell King5413f742009-11-20 11:25:44 +0000923 local_clk_disable(clk);
Vitaly Wool78818e42006-05-16 11:54:37 +0100924 clock_unlock();
925}
926
Vitaly Woole9931b52006-06-22 10:26:20 +0100927EXPORT_SYMBOL(clk_disable);
Vitaly Wool78818e42006-05-16 11:54:37 +0100928
929long clk_round_rate(struct clk *clk, unsigned long rate)
930{
931 long ret;
932 clock_lock();
933 if (clk->round_rate)
934 ret = clk->round_rate(clk, rate);
935 else
936 ret = clk->rate;
937 clock_unlock();
938 return ret;
939}
940
941EXPORT_SYMBOL(clk_round_rate);
942
943int clk_set_parent(struct clk *clk, struct clk *parent)
944{
945 int ret = -ENODEV;
946 if (!clk->set_parent)
947 goto out;
948
949 clock_lock();
950 ret = clk->set_parent(clk, parent);
951 if (!ret)
952 clk->parent = parent;
953 clock_unlock();
954
955out:
956 return ret;
957}
958
959EXPORT_SYMBOL(clk_set_parent);
960
961static int __init clk_init(void)
962{
963 struct clk **clkp;
964
965 /* Disable autoclocking, as it doesn't seem to work */
966 __raw_writel(0xff, AUTOCLK_CTRL);
967
968 for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
969 clkp++) {
Russell King0c452df2009-11-20 11:28:59 +0000970 struct clk *clk = *clkp;
971 if (clk->flags & NEEDS_INITIALIZATION) {
972 if (clk->set_rate) {
973 clk->user_rate = clk->rate;
974 local_set_rate(clk, clk->user_rate);
975 if (clk->set_parent)
976 clk->set_parent(clk, clk->parent);
977 }
978 if (clk->enable && clk->usecount)
979 clk->enable(clk);
980 if (clk->disable && !clk->usecount)
981 clk->disable(clk);
Vitaly Wool78818e42006-05-16 11:54:37 +0100982 }
983 pr_debug("%s: clock %s, rate %ld\n",
Russell King0c452df2009-11-20 11:28:59 +0000984 __func__, clk->name, clk->rate);
Vitaly Wool78818e42006-05-16 11:54:37 +0100985 }
986
Russell King5413f742009-11-20 11:25:44 +0000987 local_clk_enable(&ck_pll4);
Vitaly Wool78818e42006-05-16 11:54:37 +0100988
989 /* if ck_13MHz is not used, disable it. */
990 if (ck_13MHz.usecount == 0)
991 local_clk_disable(&ck_13MHz);
992
993 /* Disable autoclocking */
994 __raw_writeb(0xff, AUTOCLK_CTRL);
995
Russell King6985a5a2009-11-20 10:32:41 +0000996 clkdev_add_table(onchip_clkreg, ARRAY_SIZE(onchip_clkreg));
997
Vitaly Wool78818e42006-05-16 11:54:37 +0100998 return 0;
999}
1000
1001arch_initcall(clk_init);