ARM: OMAP: Fix 32 kHz timer and modify GP timer to use GPT1
[linux-2.6] / arch / arm / mach-omap2 / clock.c
1 /*
2  *  linux/arch/arm/mach-omap2/clock.c
3  *
4  *  Copyright (C) 2005 Texas Instruments Inc.
5  *  Richard Woodruff <r-woodruff2@ti.com>
6  *  Created for OMAP2.
7  *
8  *  Cleaned up and modified to use omap shared clock framework by
9  *  Tony Lindgren <tony@atomide.com>
10  *
11  *  Based on omap1 clock.c, Copyright (C) 2004 - 2005 Nokia corporation
12  *  Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License version 2 as
16  * published by the Free Software Foundation.
17  */
18 #include <linux/config.h>
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/device.h>
22 #include <linux/list.h>
23 #include <linux/errno.h>
24 #include <linux/delay.h>
25 #include <linux/clk.h>
26
27 #include <asm/io.h>
28
29 #include <asm/arch/clock.h>
30 #include <asm/arch/sram.h>
31
32 #include "prcm-regs.h"
33 #include "memory.h"
34 #include "clock.h"
35
36 //#define DOWN_VARIABLE_DPLL 1                  /* Experimental */
37
38 static struct prcm_config *curr_prcm_set;
39 static u32 curr_perf_level = PRCM_FULL_SPEED;
40
41 /*-------------------------------------------------------------------------
42  * Omap2 specific clock functions
43  *-------------------------------------------------------------------------*/
44
45 /* Recalculate SYST_CLK */
46 static void omap2_sys_clk_recalc(struct clk * clk)
47 {
48         u32 div = PRCM_CLKSRC_CTRL;
49         div &= (1 << 7) | (1 << 6);     /* Test if ext clk divided by 1 or 2 */
50         div >>= clk->rate_offset;
51         clk->rate = (clk->parent->rate / div);
52         propagate_rate(clk);
53 }
54
55 static u32 omap2_get_dpll_rate(struct clk * tclk)
56 {
57         long long dpll_clk;
58         int dpll_mult, dpll_div, amult;
59
60         dpll_mult = (CM_CLKSEL1_PLL >> 12) & 0x03ff;    /* 10 bits */
61         dpll_div = (CM_CLKSEL1_PLL >> 8) & 0x0f;        /* 4 bits */
62         dpll_clk = (long long)tclk->parent->rate * dpll_mult;
63         do_div(dpll_clk, dpll_div + 1);
64         amult = CM_CLKSEL2_PLL & 0x3;
65         dpll_clk *= amult;
66
67         return dpll_clk;
68 }
69
70 static void omap2_followparent_recalc(struct clk *clk)
71 {
72         followparent_recalc(clk);
73 }
74
75 static void omap2_propagate_rate(struct clk * clk)
76 {
77         if (!(clk->flags & RATE_FIXED))
78                 clk->rate = clk->parent->rate;
79
80         propagate_rate(clk);
81 }
82
83 /* Enable an APLL if off */
84 static void omap2_clk_fixed_enable(struct clk *clk)
85 {
86         u32 cval, i=0;
87
88         if (clk->enable_bit == 0xff)                    /* Parent will do it */
89                 return;
90
91         cval = CM_CLKEN_PLL;
92
93         if ((cval & (0x3 << clk->enable_bit)) == (0x3 << clk->enable_bit))
94                 return;
95
96         cval &= ~(0x3 << clk->enable_bit);
97         cval |= (0x3 << clk->enable_bit);
98         CM_CLKEN_PLL = cval;
99
100         if (clk == &apll96_ck)
101                 cval = (1 << 8);
102         else if (clk == &apll54_ck)
103                 cval = (1 << 6);
104
105         while (!CM_IDLEST_CKGEN & cval) {               /* Wait for lock */
106                 ++i;
107                 udelay(1);
108                 if (i == 100000)
109                         break;
110         }
111 }
112
113 /* Enables clock without considering parent dependencies or use count
114  * REVISIT: Maybe change this to use clk->enable like on omap1?
115  */
116 static int _omap2_clk_enable(struct clk * clk)
117 {
118         u32 regval32;
119
120         if (clk->flags & ALWAYS_ENABLED)
121                 return 0;
122
123         if (unlikely(clk->enable_reg == 0)) {
124                 printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
125                        clk->name);
126                 return 0;
127         }
128
129         if (clk->enable_reg == (void __iomem *)&CM_CLKEN_PLL) {
130                 omap2_clk_fixed_enable(clk);
131                 return 0;
132         }
133
134         regval32 = __raw_readl(clk->enable_reg);
135         regval32 |= (1 << clk->enable_bit);
136         __raw_writel(regval32, clk->enable_reg);
137
138         return 0;
139 }
140
141 /* Stop APLL */
142 static void omap2_clk_fixed_disable(struct clk *clk)
143 {
144         u32 cval;
145
146         if(clk->enable_bit == 0xff)             /* let parent off do it */
147                 return;
148
149         cval = CM_CLKEN_PLL;
150         cval &= ~(0x3 << clk->enable_bit);
151         CM_CLKEN_PLL = cval;
152 }
153
154 /* Disables clock without considering parent dependencies or use count */
155 static void _omap2_clk_disable(struct clk *clk)
156 {
157         u32 regval32;
158
159         if (clk->enable_reg == 0)
160                 return;
161
162         if (clk->enable_reg == (void __iomem *)&CM_CLKEN_PLL) {
163                 omap2_clk_fixed_disable(clk);
164                 return;
165         }
166
167         regval32 = __raw_readl(clk->enable_reg);
168         regval32 &= ~(1 << clk->enable_bit);
169         __raw_writel(regval32, clk->enable_reg);
170 }
171
172 static int omap2_clk_enable(struct clk *clk)
173 {
174         int ret = 0;
175
176         if (clk->usecount++ == 0) {
177                 if (likely((u32)clk->parent))
178                         ret = omap2_clk_enable(clk->parent);
179
180                 if (unlikely(ret != 0)) {
181                         clk->usecount--;
182                         return ret;
183                 }
184
185                 ret = _omap2_clk_enable(clk);
186
187                 if (unlikely(ret != 0) && clk->parent) {
188                         omap2_clk_disable(clk->parent);
189                         clk->usecount--;
190                 }
191         }
192
193         return ret;
194 }
195
196 static void omap2_clk_disable(struct clk *clk)
197 {
198         if (clk->usecount > 0 && !(--clk->usecount)) {
199                 _omap2_clk_disable(clk);
200                 if (likely((u32)clk->parent))
201                         omap2_clk_disable(clk->parent);
202         }
203 }
204
205 /*
206  * Uses the current prcm set to tell if a rate is valid.
207  * You can go slower, but not faster within a given rate set.
208  */
209 static u32 omap2_dpll_round_rate(unsigned long target_rate)
210 {
211         u32 high, low;
212
213         if ((CM_CLKSEL2_PLL & 0x3) == 1) {      /* DPLL clockout */
214                 high = curr_prcm_set->dpll_speed * 2;
215                 low = curr_prcm_set->dpll_speed;
216         } else {                                /* DPLL clockout x 2 */
217                 high = curr_prcm_set->dpll_speed;
218                 low = curr_prcm_set->dpll_speed / 2;
219         }
220
221 #ifdef DOWN_VARIABLE_DPLL
222         if (target_rate > high)
223                 return high;
224         else
225                 return target_rate;
226 #else
227         if (target_rate > low)
228                 return high;
229         else
230                 return low;
231 #endif
232
233 }
234
235 /*
236  * Used for clocks that are part of CLKSEL_xyz governed clocks.
237  * REVISIT: Maybe change to use clk->enable() functions like on omap1?
238  */
239 static void omap2_clksel_recalc(struct clk * clk)
240 {
241         u32 fixed = 0, div = 0;
242
243         if (clk == &dpll_ck) {
244                 clk->rate = omap2_get_dpll_rate(clk);
245                 fixed = 1;
246                 div = 0;
247         }
248
249         if (clk == &iva1_mpu_int_ifck) {
250                 div = 2;
251                 fixed = 1;
252         }
253
254         if ((clk == &dss1_fck) && ((CM_CLKSEL1_CORE & (0x1f << 8)) == 0)) {
255                 clk->rate = sys_ck.rate;
256                 return;
257         }
258
259         if (!fixed) {
260                 div = omap2_clksel_get_divisor(clk);
261                 if (div == 0)
262                         return;
263         }
264
265         if (div != 0) {
266                 if (unlikely(clk->rate == clk->parent->rate / div))
267                         return;
268                 clk->rate = clk->parent->rate / div;
269         }
270
271         if (unlikely(clk->flags & RATE_PROPAGATES))
272                 propagate_rate(clk);
273 }
274
275 /*
276  * Finds best divider value in an array based on the source and target
277  * rates. The divider array must be sorted with smallest divider first.
278  */
279 static inline u32 omap2_divider_from_table(u32 size, u32 *div_array,
280                                            u32 src_rate, u32 tgt_rate)
281 {
282         int i, test_rate;
283
284         if (div_array == NULL)
285                 return ~1;
286
287         for (i=0; i < size; i++) {
288                 test_rate = src_rate / *div_array;
289                 if (test_rate <= tgt_rate)
290                         return *div_array;
291                 ++div_array;
292         }
293
294         return ~0;      /* No acceptable divider */
295 }
296
297 /*
298  * Find divisor for the given clock and target rate.
299  *
300  * Note that this will not work for clocks which are part of CONFIG_PARTICIPANT,
301  * they are only settable as part of virtual_prcm set.
302  */
303 static u32 omap2_clksel_round_rate(struct clk *tclk, u32 target_rate,
304         u32 *new_div)
305 {
306         u32 gfx_div[] = {2, 3, 4};
307         u32 sysclkout_div[] = {1, 2, 4, 8, 16};
308         u32 dss1_div[] = {1, 2, 3, 4, 5, 6, 8, 9, 12, 16};
309         u32 vylnq_div[] = {1, 2, 3, 4, 6, 8, 9, 12, 16, 18};
310         u32 best_div = ~0, asize = 0;
311         u32 *div_array = NULL;
312
313         switch (tclk->flags & SRC_RATE_SEL_MASK) {
314         case CM_GFX_SEL1:
315                 asize = 3;
316                 div_array = gfx_div;
317                 break;
318         case CM_PLL_SEL1:
319                 return omap2_dpll_round_rate(target_rate);
320         case CM_SYSCLKOUT_SEL1:
321                 asize = 5;
322                 div_array = sysclkout_div;
323                 break;
324         case CM_CORE_SEL1:
325                 if(tclk == &dss1_fck){
326                         if(tclk->parent == &core_ck){
327                                 asize = 10;
328                                 div_array = dss1_div;
329                         } else {
330                                 *new_div = 0; /* fixed clk */
331                                 return(tclk->parent->rate);
332                         }
333                 } else if((tclk == &vlynq_fck) && cpu_is_omap2420()){
334                         if(tclk->parent == &core_ck){
335                                 asize = 10;
336                                 div_array = vylnq_div;
337                         } else {
338                                 *new_div = 0; /* fixed clk */
339                                 return(tclk->parent->rate);
340                         }
341                 }
342                 break;
343         }
344
345         best_div = omap2_divider_from_table(asize, div_array,
346          tclk->parent->rate, target_rate);
347         if (best_div == ~0){
348                 *new_div = 1;
349                 return best_div; /* signal error */
350         }
351
352         *new_div = best_div;
353         return (tclk->parent->rate / best_div);
354 }
355
356 /* Given a clock and a rate apply a clock specific rounding function */
357 static long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
358 {
359         u32 new_div = 0;
360         int valid_rate;
361
362         if (clk->flags & RATE_FIXED)
363                 return clk->rate;
364
365         if (clk->flags & RATE_CKCTL) {
366                 valid_rate = omap2_clksel_round_rate(clk, rate, &new_div);
367                 return valid_rate;
368         }
369
370         if (clk->round_rate != 0)
371                 return clk->round_rate(clk, rate);
372
373         return clk->rate;
374 }
375
376 /*
377  * Check the DLL lock state, and return tue if running in unlock mode.
378  * This is needed to compenste for the shifted DLL value in unlock mode.
379  */
380 static u32 omap2_dll_force_needed(void)
381 {
382         u32 dll_state = SDRC_DLLA_CTRL;         /* dlla and dllb are a set */
383
384         if ((dll_state & (1 << 2)) == (1 << 2))
385                 return 1;
386         else
387                 return 0;
388 }
389
390 static u32 omap2_reprogram_sdrc(u32 level, u32 force)
391 {
392         u32 slow_dll_ctrl, fast_dll_ctrl, m_type;
393         u32 prev = curr_perf_level, flags;
394
395         if ((curr_perf_level == level) && !force)
396                 return prev;
397
398         m_type = omap2_memory_get_type();
399         slow_dll_ctrl = omap2_memory_get_slow_dll_ctrl();
400         fast_dll_ctrl = omap2_memory_get_fast_dll_ctrl();
401
402         if (level == PRCM_HALF_SPEED) {
403                 local_irq_save(flags);
404                 PRCM_VOLTSETUP = 0xffff;
405                 omap2_sram_reprogram_sdrc(PRCM_HALF_SPEED,
406                                           slow_dll_ctrl, m_type);
407                 curr_perf_level = PRCM_HALF_SPEED;
408                 local_irq_restore(flags);
409         }
410         if (level == PRCM_FULL_SPEED) {
411                 local_irq_save(flags);
412                 PRCM_VOLTSETUP = 0xffff;
413                 omap2_sram_reprogram_sdrc(PRCM_FULL_SPEED,
414                                           fast_dll_ctrl, m_type);
415                 curr_perf_level = PRCM_FULL_SPEED;
416                 local_irq_restore(flags);
417         }
418
419         return prev;
420 }
421
422 static int omap2_reprogram_dpll(struct clk * clk, unsigned long rate)
423 {
424         u32 flags, cur_rate, low, mult, div, valid_rate, done_rate;
425         u32 bypass = 0;
426         struct prcm_config tmpset;
427         int ret = -EINVAL;
428
429         local_irq_save(flags);
430         cur_rate = omap2_get_dpll_rate(&dpll_ck);
431         mult = CM_CLKSEL2_PLL & 0x3;
432
433         if ((rate == (cur_rate / 2)) && (mult == 2)) {
434                 omap2_reprogram_sdrc(PRCM_HALF_SPEED, 1);
435         } else if ((rate == (cur_rate * 2)) && (mult == 1)) {
436                 omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1);
437         } else if (rate != cur_rate) {
438                 valid_rate = omap2_dpll_round_rate(rate);
439                 if (valid_rate != rate)
440                         goto dpll_exit;
441
442                 if ((CM_CLKSEL2_PLL & 0x3) == 1)
443                         low = curr_prcm_set->dpll_speed;
444                 else
445                         low = curr_prcm_set->dpll_speed / 2;
446
447                 tmpset.cm_clksel1_pll = CM_CLKSEL1_PLL;
448                 tmpset.cm_clksel1_pll &= ~(0x3FFF << 8);
449                 div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
450                 tmpset.cm_clksel2_pll = CM_CLKSEL2_PLL;
451                 tmpset.cm_clksel2_pll &= ~0x3;
452                 if (rate > low) {
453                         tmpset.cm_clksel2_pll |= 0x2;
454                         mult = ((rate / 2) / 1000000);
455                         done_rate = PRCM_FULL_SPEED;
456                 } else {
457                         tmpset.cm_clksel2_pll |= 0x1;
458                         mult = (rate / 1000000);
459                         done_rate = PRCM_HALF_SPEED;
460                 }
461                 tmpset.cm_clksel1_pll |= ((div << 8) | (mult << 12));
462
463                 /* Worst case */
464                 tmpset.base_sdrc_rfr = V24XX_SDRC_RFR_CTRL_BYPASS;
465
466                 if (rate == curr_prcm_set->xtal_speed)  /* If asking for 1-1 */
467                         bypass = 1;
468
469                 omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1); /* For init_mem */
470
471                 /* Force dll lock mode */
472                 omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
473                                bypass);
474
475                 /* Errata: ret dll entry state */
476                 omap2_init_memory_params(omap2_dll_force_needed());
477                 omap2_reprogram_sdrc(done_rate, 0);
478         }
479         omap2_clksel_recalc(&dpll_ck);
480         ret = 0;
481
482 dpll_exit:
483         local_irq_restore(flags);
484         return(ret);
485 }
486
487 /* Just return the MPU speed */
488 static void omap2_mpu_recalc(struct clk * clk)
489 {
490         clk->rate = curr_prcm_set->mpu_speed;
491 }
492
493 /*
494  * Look for a rate equal or less than the target rate given a configuration set.
495  *
496  * What's not entirely clear is "which" field represents the key field.
497  * Some might argue L3-DDR, others ARM, others IVA. This code is simple and
498  * just uses the ARM rates.
499  */
500 static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate)
501 {
502         struct prcm_config * ptr;
503         long highest_rate;
504
505         if (clk != &virt_prcm_set)
506                 return -EINVAL;
507
508         highest_rate = -EINVAL;
509
510         for (ptr = rate_table; ptr->mpu_speed; ptr++) {
511                 if (ptr->xtal_speed != sys_ck.rate)
512                         continue;
513
514                 highest_rate = ptr->mpu_speed;
515
516                 /* Can check only after xtal frequency check */
517                 if (ptr->mpu_speed <= rate)
518                         break;
519         }
520         return highest_rate;
521 }
522
523 /*
524  * omap2_convert_field_to_div() - turn field value into integer divider
525  */
526 static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val)
527 {
528         u32 i;
529         u32 clkout_array[] = {1, 2, 4, 8, 16};
530
531         if ((div_sel & SRC_RATE_SEL_MASK) == CM_SYSCLKOUT_SEL1) {
532                 for (i = 0; i < 5; i++) {
533                         if (field_val == i)
534                                 return clkout_array[i];
535                 }
536                 return ~0;
537         } else
538                 return field_val;
539 }
540
541 /*
542  * Returns the CLKSEL divider register value
543  * REVISIT: This should be cleaned up to work nicely with void __iomem *
544  */
545 static u32 omap2_get_clksel(u32 *div_sel, u32 *field_mask,
546                             struct clk *clk)
547 {
548         int ret = ~0;
549         u32 reg_val, div_off;
550         u32 div_addr = 0;
551         u32 mask = ~0;
552
553         div_off = clk->rate_offset;
554
555         switch ((*div_sel & SRC_RATE_SEL_MASK)) {
556         case CM_MPU_SEL1:
557                 div_addr = (u32)&CM_CLKSEL_MPU;
558                 mask = 0x1f;
559                 break;
560         case CM_DSP_SEL1:
561                 div_addr = (u32)&CM_CLKSEL_DSP;
562                 if (cpu_is_omap2420()) {
563                         if ((div_off == 0) || (div_off == 8))
564                                 mask = 0x1f;
565                         else if (div_off == 5)
566                                 mask = 0x3;
567                 } else if (cpu_is_omap2430()) {
568                         if (div_off == 0)
569                                 mask = 0x1f;
570                         else if (div_off == 5)
571                                 mask = 0x3;
572                 }
573                 break;
574         case CM_GFX_SEL1:
575                 div_addr = (u32)&CM_CLKSEL_GFX;
576                 if (div_off == 0)
577                         mask = 0x7;
578                 break;
579         case CM_MODEM_SEL1:
580                 div_addr = (u32)&CM_CLKSEL_MDM;
581                 if (div_off == 0)
582                         mask = 0xf;
583                 break;
584         case CM_SYSCLKOUT_SEL1:
585                 div_addr = (u32)&PRCM_CLKOUT_CTRL;
586                 if ((div_off == 3) || (div_off = 11))
587                         mask= 0x3;
588                 break;
589         case CM_CORE_SEL1:
590                 div_addr = (u32)&CM_CLKSEL1_CORE;
591                 switch (div_off) {
592                 case 0:                                 /* l3 */
593                 case 8:                                 /* dss1 */
594                 case 15:                                /* vylnc-2420 */
595                 case 20:                                /* ssi */
596                         mask = 0x1f; break;
597                 case 5:                                 /* l4 */
598                         mask = 0x3; break;
599                 case 13:                                /* dss2 */
600                         mask = 0x1; break;
601                 case 25:                                /* usb */
602                         mask = 0x7; break;
603                 }
604         }
605
606         *field_mask = mask;
607
608         if (unlikely(mask == ~0))
609                 div_addr = 0;
610
611         *div_sel = div_addr;
612
613         if (unlikely(div_addr == 0))
614                 return ret;
615
616         /* Isolate field */
617         reg_val = __raw_readl((void __iomem *)div_addr) & (mask << div_off);
618
619         /* Normalize back to divider value */
620         reg_val >>= div_off;
621
622         return reg_val;
623 }
624
625 /*
626  * Return divider to be applied to parent clock.
627  * Return 0 on error.
628  */
629 static u32 omap2_clksel_get_divisor(struct clk *clk)
630 {
631         int ret = 0;
632         u32 div, div_sel, div_off, field_mask, field_val;
633
634         /* isolate control register */
635         div_sel = (SRC_RATE_SEL_MASK & clk->flags);
636
637         div_off = clk->rate_offset;
638         field_val = omap2_get_clksel(&div_sel, &field_mask, clk);
639         if (div_sel == 0)
640                 return ret;
641
642         div_sel = (SRC_RATE_SEL_MASK & clk->flags);
643         div = omap2_clksel_to_divisor(div_sel, field_val);
644
645         return div;
646 }
647
648 /* Set the clock rate for a clock source */
649 static int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
650
651 {
652         int ret = -EINVAL;
653         void __iomem * reg;
654         u32 div_sel, div_off, field_mask, field_val, reg_val, validrate;
655         u32 new_div = 0;
656
657         if (!(clk->flags & CONFIG_PARTICIPANT) && (clk->flags & RATE_CKCTL)) {
658                 if (clk == &dpll_ck)
659                         return omap2_reprogram_dpll(clk, rate);
660
661                 /* Isolate control register */
662                 div_sel = (SRC_RATE_SEL_MASK & clk->flags);
663                 div_off = clk->rate_offset;
664
665                 validrate = omap2_clksel_round_rate(clk, rate, &new_div);
666                 if (validrate != rate)
667                         return(ret);
668
669                 field_val = omap2_get_clksel(&div_sel, &field_mask, clk);
670                 if (div_sel == 0)
671                         return ret;
672
673                 if (clk->flags & CM_SYSCLKOUT_SEL1) {
674                         switch (new_div) {
675                         case 16:
676                                 field_val = 4;
677                                 break;
678                         case 8:
679                                 field_val = 3;
680                                 break;
681                         case 4:
682                                 field_val = 2;
683                                 break;
684                         case 2:
685                                 field_val = 1;
686                                 break;
687                         case 1:
688                                 field_val = 0;
689                                 break;
690                         }
691                 } else
692                         field_val = new_div;
693
694                 reg = (void __iomem *)div_sel;
695
696                 reg_val = __raw_readl(reg);
697                 reg_val &= ~(field_mask << div_off);
698                 reg_val |= (field_val << div_off);
699
700                 __raw_writel(reg_val, reg);
701                 clk->rate = clk->parent->rate / field_val;
702
703                 if (clk->flags & DELAYED_APP)
704                         __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
705                 ret = 0;
706         } else if (clk->set_rate != 0)
707                 ret = clk->set_rate(clk, rate);
708
709         if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
710                 propagate_rate(clk);
711
712         return ret;
713 }
714
715 /* Converts encoded control register address into a full address */
716 static u32 omap2_get_src_field(u32 *type_to_addr, u32 reg_offset,
717                                struct clk *src_clk, u32 *field_mask)
718 {
719         u32 val = ~0, src_reg_addr = 0, mask = 0;
720
721         /* Find target control register.*/
722         switch ((*type_to_addr & SRC_RATE_SEL_MASK)) {
723         case CM_CORE_SEL1:
724                 src_reg_addr = (u32)&CM_CLKSEL1_CORE;
725                 if (reg_offset == 13) {                 /* DSS2_fclk */
726                         mask = 0x1;
727                         if (src_clk == &sys_ck)
728                                 val = 0;
729                         if (src_clk == &func_48m_ck)
730                                 val = 1;
731                 } else if (reg_offset == 8) {           /* DSS1_fclk */
732                         mask = 0x1f;
733                         if (src_clk == &sys_ck)
734                                 val = 0;
735                         else if (src_clk == &core_ck)   /* divided clock */
736                                 val = 0x10;             /* rate needs fixing */
737                 } else if ((reg_offset == 15) && cpu_is_omap2420()){ /*vlnyq*/
738                         mask = 0x1F;
739                         if(src_clk == &func_96m_ck)
740                                 val = 0;
741                         else if (src_clk == &core_ck)
742                                 val = 0x10;
743                 }
744                 break;
745         case CM_CORE_SEL2:
746                 src_reg_addr = (u32)&CM_CLKSEL2_CORE;
747                 mask = 0x3;
748                 if (src_clk == &func_32k_ck)
749                         val = 0x0;
750                 if (src_clk == &sys_ck)
751                         val = 0x1;
752                 if (src_clk == &alt_ck)
753                         val = 0x2;
754                 break;
755         case CM_WKUP_SEL1:
756                 src_reg_addr = (u32)&CM_CLKSEL_WKUP;
757                 mask = 0x3;
758                 if (src_clk == &func_32k_ck)
759                         val = 0x0;
760                 if (src_clk == &sys_ck)
761                         val = 0x1;
762                 if (src_clk == &alt_ck)
763                         val = 0x2;
764                 break;
765         case CM_PLL_SEL1:
766                 src_reg_addr = (u32)&CM_CLKSEL1_PLL;
767                 mask = 0x1;
768                 if (reg_offset == 0x3) {
769                         if (src_clk == &apll96_ck)
770                                 val = 0;
771                         if (src_clk == &alt_ck)
772                                 val = 1;
773                 }
774                 else if (reg_offset == 0x5) {
775                         if (src_clk == &apll54_ck)
776                                 val = 0;
777                         if (src_clk == &alt_ck)
778                                 val = 1;
779                 }
780                 break;
781         case CM_PLL_SEL2:
782                 src_reg_addr = (u32)&CM_CLKSEL2_PLL;
783                 mask = 0x3;
784                 if (src_clk == &func_32k_ck)
785                         val = 0x0;
786                 if (src_clk == &dpll_ck)
787                         val = 0x2;
788                 break;
789         case CM_SYSCLKOUT_SEL1:
790                 src_reg_addr = (u32)&PRCM_CLKOUT_CTRL;
791                 mask = 0x3;
792                 if (src_clk == &dpll_ck)
793                         val = 0;
794                 if (src_clk == &sys_ck)
795                         val = 1;
796                 if (src_clk == &func_96m_ck)
797                         val = 2;
798                 if (src_clk == &func_54m_ck)
799                         val = 3;
800                 break;
801         }
802
803         if (val == ~0)                  /* Catch errors in offset */
804                 *type_to_addr = 0;
805         else
806                 *type_to_addr = src_reg_addr;
807         *field_mask = mask;
808
809         return val;
810 }
811
812 static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
813 {
814         void __iomem * reg;
815         u32 src_sel, src_off, field_val, field_mask, reg_val, rate;
816         int ret = -EINVAL;
817
818         if (unlikely(clk->flags & CONFIG_PARTICIPANT))
819                 return ret;
820
821         if (clk->flags & SRC_SEL_MASK) {        /* On-chip SEL collection */
822                 src_sel = (SRC_RATE_SEL_MASK & clk->flags);
823                 src_off = clk->src_offset;
824
825                 if (src_sel == 0)
826                         goto set_parent_error;
827
828                 field_val = omap2_get_src_field(&src_sel, src_off, new_parent,
829                                                 &field_mask);
830
831                 reg = (void __iomem *)src_sel;
832
833                 if (clk->usecount > 0)
834                         _omap2_clk_disable(clk);
835
836                 /* Set new source value (previous dividers if any in effect) */
837                 reg_val = __raw_readl(reg) & ~(field_mask << src_off);
838                 reg_val |= (field_val << src_off);
839                 __raw_writel(reg_val, reg);
840
841                 if (clk->flags & DELAYED_APP)
842                         __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
843
844                 if (clk->usecount > 0)
845                         _omap2_clk_enable(clk);
846
847                 clk->parent = new_parent;
848
849                 /* SRC_RATE_SEL_MASK clocks follow their parents rates.*/
850                 if ((new_parent == &core_ck) && (clk == &dss1_fck))
851                         clk->rate = new_parent->rate / 0x10;
852                 else
853                         clk->rate = new_parent->rate;
854
855                 if (unlikely(clk->flags & RATE_PROPAGATES))
856                         propagate_rate(clk);
857
858                 return 0;
859         } else {
860                 clk->parent = new_parent;
861                 rate = new_parent->rate;
862                 omap2_clk_set_rate(clk, rate);
863                 ret = 0;
864         }
865
866  set_parent_error:
867         return ret;
868 }
869
870 /* Sets basic clocks based on the specified rate */
871 static int omap2_select_table_rate(struct clk * clk, unsigned long rate)
872 {
873         u32 flags, cur_rate, done_rate, bypass = 0;
874         u8 cpu_mask = 0;
875         struct prcm_config *prcm;
876         unsigned long found_speed = 0;
877
878         if (clk != &virt_prcm_set)
879                 return -EINVAL;
880
881         /* FIXME: Change cpu_is_omap2420() to cpu_is_omap242x() */
882         if (cpu_is_omap2420())
883                 cpu_mask = RATE_IN_242X;
884         else if (cpu_is_omap2430())
885                 cpu_mask = RATE_IN_243X;
886
887         for (prcm = rate_table; prcm->mpu_speed; prcm++) {
888                 if (!(prcm->flags & cpu_mask))
889                         continue;
890
891                 if (prcm->xtal_speed != sys_ck.rate)
892                         continue;
893
894                 if (prcm->mpu_speed <= rate) {
895                         found_speed = prcm->mpu_speed;
896                         break;
897                 }
898         }
899
900         if (!found_speed) {
901                 printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
902          rate / 1000000);
903                 return -EINVAL;
904         }
905
906         curr_prcm_set = prcm;
907         cur_rate = omap2_get_dpll_rate(&dpll_ck);
908
909         if (prcm->dpll_speed == cur_rate / 2) {
910                 omap2_reprogram_sdrc(PRCM_HALF_SPEED, 1);
911         } else if (prcm->dpll_speed == cur_rate * 2) {
912                 omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1);
913         } else if (prcm->dpll_speed != cur_rate) {
914                 local_irq_save(flags);
915
916                 if (prcm->dpll_speed == prcm->xtal_speed)
917                         bypass = 1;
918
919                 if ((prcm->cm_clksel2_pll & 0x3) == 2)
920                         done_rate = PRCM_FULL_SPEED;
921                 else
922                         done_rate = PRCM_HALF_SPEED;
923
924                 /* MPU divider */
925                 CM_CLKSEL_MPU = prcm->cm_clksel_mpu;
926
927                 /* dsp + iva1 div(2420), iva2.1(2430) */
928                 CM_CLKSEL_DSP = prcm->cm_clksel_dsp;
929
930                 CM_CLKSEL_GFX = prcm->cm_clksel_gfx;
931
932                 /* Major subsystem dividers */
933                 CM_CLKSEL1_CORE = prcm->cm_clksel1_core;
934                 if (cpu_is_omap2430())
935                         CM_CLKSEL_MDM = prcm->cm_clksel_mdm;
936
937                 /* x2 to enter init_mem */
938                 omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1);
939
940                 omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
941                                bypass);
942
943                 omap2_init_memory_params(omap2_dll_force_needed());
944                 omap2_reprogram_sdrc(done_rate, 0);
945
946                 local_irq_restore(flags);
947         }
948         omap2_clksel_recalc(&dpll_ck);
949
950         return 0;
951 }
952
953 /*-------------------------------------------------------------------------
954  * Omap2 clock reset and init functions
955  *-------------------------------------------------------------------------*/
956
957 static struct clk_functions omap2_clk_functions = {
958         .clk_enable             = omap2_clk_enable,
959         .clk_disable            = omap2_clk_disable,
960         .clk_round_rate         = omap2_clk_round_rate,
961         .clk_set_rate           = omap2_clk_set_rate,
962         .clk_set_parent         = omap2_clk_set_parent,
963 };
964
965 static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys)
966 {
967         u32 div, aplls, sclk = 13000000;
968
969         aplls = CM_CLKSEL1_PLL;
970         aplls &= ((1 << 23) | (1 << 24) | (1 << 25));
971         aplls >>= 23;                   /* Isolate field, 0,2,3 */
972
973         if (aplls == 0)
974                 sclk = 19200000;
975         else if (aplls == 2)
976                 sclk = 13000000;
977         else if (aplls == 3)
978                 sclk = 12000000;
979
980         div = PRCM_CLKSRC_CTRL;
981         div &= ((1 << 7) | (1 << 6));
982         div >>= sys->rate_offset;
983
984         osc->rate = sclk * div;
985         sys->rate = sclk;
986 }
987
988 #ifdef CONFIG_OMAP_RESET_CLOCKS
989 static void __init omap2_disable_unused_clocks(void)
990 {
991         struct clk *ck;
992         u32 regval32;
993
994         list_for_each_entry(ck, &clocks, node) {
995                 if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED) ||
996                         ck->enable_reg == 0)
997                         continue;
998
999                 regval32 = __raw_readl(ck->enable_reg);
1000                 if ((regval32 & (1 << ck->enable_bit)) == 0)
1001                         continue;
1002
1003                 printk(KERN_INFO "Disabling unused clock \"%s\"\n", ck->name);
1004                 _omap2_clk_disable(ck);
1005         }
1006 }
1007 late_initcall(omap2_disable_unused_clocks);
1008 #endif
1009
1010 /*
1011  * Switch the MPU rate if specified on cmdline.
1012  * We cannot do this early until cmdline is parsed.
1013  */
1014 static int __init omap2_clk_arch_init(void)
1015 {
1016         if (!mpurate)
1017                 return -EINVAL;
1018
1019         if (omap2_select_table_rate(&virt_prcm_set, mpurate))
1020                 printk(KERN_ERR "Could not find matching MPU rate\n");
1021
1022         propagate_rate(&osc_ck);                /* update main root fast */
1023         propagate_rate(&func_32k_ck);           /* update main root slow */
1024
1025         printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL/MPU): "
1026                "%ld.%01ld/%ld/%ld MHz\n",
1027                (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
1028                (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
1029
1030         return 0;
1031 }
1032 arch_initcall(omap2_clk_arch_init);
1033
1034 int __init omap2_clk_init(void)
1035 {
1036         struct prcm_config *prcm;
1037         struct clk ** clkp;
1038         u32 clkrate;
1039
1040         clk_init(&omap2_clk_functions);
1041         omap2_get_crystal_rate(&osc_ck, &sys_ck);
1042
1043         for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
1044              clkp++) {
1045
1046                 if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) {
1047                         clk_register(*clkp);
1048                         continue;
1049                 }
1050
1051                 if ((*clkp)->flags & CLOCK_IN_OMAP243X && cpu_is_omap2430()) {
1052                         clk_register(*clkp);
1053                         continue;
1054                 }
1055         }
1056
1057         /* Check the MPU rate set by bootloader */
1058         clkrate = omap2_get_dpll_rate(&dpll_ck);
1059         for (prcm = rate_table; prcm->mpu_speed; prcm++) {
1060                 if (prcm->xtal_speed != sys_ck.rate)
1061                         continue;
1062                 if (prcm->dpll_speed <= clkrate)
1063                          break;
1064         }
1065         curr_prcm_set = prcm;
1066
1067         propagate_rate(&osc_ck);                /* update main root fast */
1068         propagate_rate(&func_32k_ck);           /* update main root slow */
1069
1070         printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): "
1071                "%ld.%01ld/%ld/%ld MHz\n",
1072                (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
1073                (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
1074
1075         /*
1076          * Only enable those clocks we will need, let the drivers
1077          * enable other clocks as necessary
1078          */
1079         clk_enable(&sync_32k_ick);
1080         clk_enable(&omapctrl_ick);
1081         if (cpu_is_omap2430())
1082                 clk_enable(&sdrc_ick);
1083
1084         return 0;
1085 }