[ARM] 3426/1: ARM: OMAP: 1/8 Update clock framework
[linux-2.6.git] / 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->src_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: field_val = 4; break;
676                         case 8:  field_val = 3; break;
677                         case 4:  field_val = 2; break;
678                         case 2:  field_val = 1; break;
679                         case 1:  field_val = 0; break;
680                         }
681                 }
682                 else
683                         field_val = new_div;
684
685                 reg = (void __iomem *)div_sel;
686
687                 reg_val = __raw_readl(reg);
688                 reg_val &= ~(field_mask << div_off);
689                 reg_val |= (field_val << div_off);
690
691                 __raw_writel(reg_val, reg);
692                 clk->rate = clk->parent->rate / field_val;
693
694                 if (clk->flags & DELAYED_APP)
695                         __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
696                 ret = 0;
697         } else if (clk->set_rate != 0)
698                 ret = clk->set_rate(clk, rate);
699
700         if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
701                 propagate_rate(clk);
702
703         return ret;
704 }
705
706 /* Converts encoded control register address into a full address */
707 static u32 omap2_get_src_field(u32 *type_to_addr, u32 reg_offset,
708                                struct clk *src_clk, u32 *field_mask)
709 {
710         u32 val = ~0, src_reg_addr = 0, mask = 0;
711
712         /* Find target control register.*/
713         switch ((*type_to_addr & SRC_RATE_SEL_MASK)) {
714         case CM_CORE_SEL1:
715                 src_reg_addr = (u32)&CM_CLKSEL1_CORE;
716                 if (reg_offset == 13) {                 /* DSS2_fclk */
717                         mask = 0x1;
718                         if (src_clk == &sys_ck)
719                                 val = 0;
720                         if (src_clk == &func_48m_ck)
721                                 val = 1;
722                 } else if (reg_offset == 8) {           /* DSS1_fclk */
723                         mask = 0x1f;
724                         if (src_clk == &sys_ck)
725                                 val = 0;
726                         else if (src_clk == &core_ck)   /* divided clock */
727                                 val = 0x10;             /* rate needs fixing */
728                 } else if ((reg_offset == 15) && cpu_is_omap2420()){ /*vlnyq*/
729                         mask = 0x1F;
730                         if(src_clk == &func_96m_ck)
731                                 val = 0;
732                         else if (src_clk == &core_ck)
733                                 val = 0x10;
734                 }
735                 break;
736         case CM_CORE_SEL2:
737                 src_reg_addr = (u32)&CM_CLKSEL2_CORE;
738                 mask = 0x3;
739                 if (src_clk == &func_32k_ck)
740                         val = 0x0;
741                 if (src_clk == &sys_ck)
742                         val = 0x1;
743                 if (src_clk == &alt_ck)
744                         val = 0x2;
745                 break;
746         case CM_WKUP_SEL1:
747                 src_reg_addr = (u32)&CM_CLKSEL2_CORE;
748                 mask = 0x3;
749                 if (src_clk == &func_32k_ck)
750                         val = 0x0;
751                 if (src_clk == &sys_ck)
752                         val = 0x1;
753                 if (src_clk == &alt_ck)
754                         val = 0x2;
755                 break;
756         case CM_PLL_SEL1:
757                 src_reg_addr = (u32)&CM_CLKSEL1_PLL;
758                 mask = 0x1;
759                 if (reg_offset == 0x3) {
760                         if (src_clk == &apll96_ck)
761                                 val = 0;
762                         if (src_clk == &alt_ck)
763                                 val = 1;
764                 }
765                 else if (reg_offset == 0x5) {
766                         if (src_clk == &apll54_ck)
767                                 val = 0;
768                         if (src_clk == &alt_ck)
769                                 val = 1;
770                 }
771                 break;
772         case CM_PLL_SEL2:
773                 src_reg_addr = (u32)&CM_CLKSEL2_PLL;
774                 mask = 0x3;
775                 if (src_clk == &func_32k_ck)
776                         val = 0x0;
777                 if (src_clk == &dpll_ck)
778                         val = 0x2;
779                 break;
780         case CM_SYSCLKOUT_SEL1:
781                 src_reg_addr = (u32)&PRCM_CLKOUT_CTRL;
782                 mask = 0x3;
783                 if (src_clk == &dpll_ck)
784                         val = 0;
785                 if (src_clk == &sys_ck)
786                         val = 1;
787                 if (src_clk == &func_54m_ck)
788                         val = 2;
789                 if (src_clk == &func_96m_ck)
790                         val = 3;
791                 break;
792         }
793
794         if (val == ~0)                  /* Catch errors in offset */
795                 *type_to_addr = 0;
796         else
797                 *type_to_addr = src_reg_addr;
798         *field_mask = mask;
799
800         return val;
801 }
802
803 static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
804 {
805         void __iomem * reg;
806         u32 src_sel, src_off, field_val, field_mask, reg_val, rate;
807         int ret = -EINVAL;
808
809         if (unlikely(clk->flags & CONFIG_PARTICIPANT))
810                 return ret;
811
812         if (clk->flags & SRC_SEL_MASK) {        /* On-chip SEL collection */
813                 src_sel = (SRC_RATE_SEL_MASK & clk->flags);
814                 src_off = clk->src_offset;
815
816                 if (src_sel == 0)
817                         goto set_parent_error;
818
819                 field_val = omap2_get_src_field(&src_sel, src_off, new_parent,
820                                                 &field_mask);
821
822                 reg = (void __iomem *)src_sel;
823
824                 if (clk->usecount > 0)
825                         _omap2_clk_disable(clk);
826
827                 /* Set new source value (previous dividers if any in effect) */
828                 reg_val = __raw_readl(reg) & ~(field_mask << src_off);
829                 reg_val |= (field_val << src_off);
830                 __raw_writel(reg_val, reg);
831
832                 if (clk->flags & DELAYED_APP)
833                         __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
834
835                 if (clk->usecount > 0)
836                         _omap2_clk_enable(clk);
837
838                 clk->parent = new_parent;
839
840                 /* SRC_RATE_SEL_MASK clocks follow their parents rates.*/
841                 if ((new_parent == &core_ck) && (clk == &dss1_fck))
842                         clk->rate = new_parent->rate / 0x10;
843                 else
844                         clk->rate = new_parent->rate;
845
846                 if (unlikely(clk->flags & RATE_PROPAGATES))
847                         propagate_rate(clk);
848
849                 return 0;
850         } else {
851                 clk->parent = new_parent;
852                 rate = new_parent->rate;
853                 omap2_clk_set_rate(clk, rate);
854                 ret = 0;
855         }
856
857  set_parent_error:
858         return ret;
859 }
860
861 /* Sets basic clocks based on the specified rate */
862 static int omap2_select_table_rate(struct clk * clk, unsigned long rate)
863 {
864         u32 flags, cur_rate, done_rate, bypass = 0;
865         u8 cpu_mask = 0;
866         struct prcm_config *prcm;
867         unsigned long found_speed = 0;
868
869         if (clk != &virt_prcm_set)
870                 return -EINVAL;
871
872         /* FIXME: Change cpu_is_omap2420() to cpu_is_omap242x() */
873         if (cpu_is_omap2420())
874                 cpu_mask = RATE_IN_242X;
875         else if (cpu_is_omap2430())
876                 cpu_mask = RATE_IN_243X;
877
878         for (prcm = rate_table; prcm->mpu_speed; prcm++) {
879                 if (!(prcm->flags & cpu_mask))
880                         continue;
881
882                 if (prcm->xtal_speed != sys_ck.rate)
883                         continue;
884
885                 if (prcm->mpu_speed <= rate) {
886                         found_speed = prcm->mpu_speed;
887                         break;
888                 }
889         }
890
891         if (!found_speed) {
892                 printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
893          rate / 1000000);
894                 return -EINVAL;
895         }
896
897         curr_prcm_set = prcm;
898         cur_rate = omap2_get_dpll_rate(&dpll_ck);
899
900         if (prcm->dpll_speed == cur_rate / 2) {
901                 omap2_reprogram_sdrc(PRCM_HALF_SPEED, 1);
902         } else if (prcm->dpll_speed == cur_rate * 2) {
903                 omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1);
904         } else if (prcm->dpll_speed != cur_rate) {
905                 local_irq_save(flags);
906
907                 if (prcm->dpll_speed == prcm->xtal_speed)
908                         bypass = 1;
909
910                 if ((prcm->cm_clksel2_pll & 0x3) == 2)
911                         done_rate = PRCM_FULL_SPEED;
912                 else
913                         done_rate = PRCM_HALF_SPEED;
914
915                 /* MPU divider */
916                 CM_CLKSEL_MPU = prcm->cm_clksel_mpu;
917
918                 /* dsp + iva1 div(2420), iva2.1(2430) */
919                 CM_CLKSEL_DSP = prcm->cm_clksel_dsp;
920
921                 CM_CLKSEL_GFX = prcm->cm_clksel_gfx;
922
923                 /* Major subsystem dividers */
924                 CM_CLKSEL1_CORE = prcm->cm_clksel1_core;
925                 if (cpu_is_omap2430())
926                         CM_CLKSEL_MDM = prcm->cm_clksel_mdm;
927
928                 /* x2 to enter init_mem */
929                 omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1);
930
931                 omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
932                                bypass);
933
934                 omap2_init_memory_params(omap2_dll_force_needed());
935                 omap2_reprogram_sdrc(done_rate, 0);
936
937                 local_irq_restore(flags);
938         }
939         omap2_clksel_recalc(&dpll_ck);
940
941         return 0;
942 }
943
944 /*-------------------------------------------------------------------------
945  * Omap2 clock reset and init functions
946  *-------------------------------------------------------------------------*/
947
948 static struct clk_functions omap2_clk_functions = {
949         .clk_enable             = omap2_clk_enable,
950         .clk_disable            = omap2_clk_disable,
951         .clk_round_rate         = omap2_clk_round_rate,
952         .clk_set_rate           = omap2_clk_set_rate,
953         .clk_set_parent         = omap2_clk_set_parent,
954 };
955
956 static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys)
957 {
958         u32 div, aplls, sclk = 13000000;
959
960         aplls = CM_CLKSEL1_PLL;
961         aplls &= ((1 << 23) | (1 << 24) | (1 << 25));
962         aplls >>= 23;                   /* Isolate field, 0,2,3 */
963
964         if (aplls == 0)
965                 sclk = 19200000;
966         else if (aplls == 2)
967                 sclk = 13000000;
968         else if (aplls == 3)
969                 sclk = 12000000;
970
971         div = PRCM_CLKSRC_CTRL;
972         div &= ((1 << 7) | (1 << 6));
973         div >>= sys->rate_offset;
974
975         osc->rate = sclk * div;
976         sys->rate = sclk;
977 }
978
979 #ifdef CONFIG_OMAP_RESET_CLOCKS
980 static void __init omap2_disable_unused_clocks(void)
981 {
982         struct clk *ck;
983         u32 regval32;
984
985         list_for_each_entry(ck, &clocks, node) {
986                 if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED) ||
987                         ck->enable_reg == 0)
988                         continue;
989
990                 regval32 = __raw_readl(ck->enable_reg);
991                 if ((regval32 & (1 << ck->enable_bit)) == 0)
992                         continue;
993
994                 printk(KERN_INFO "Disabling unused clock \"%s\"\n", ck->name);
995                 _omap2_clk_disable(ck);
996         }
997 }
998 late_initcall(omap2_disable_unused_clocks);
999 #endif
1000
1001 /*
1002  * Switch the MPU rate if specified on cmdline.
1003  * We cannot do this early until cmdline is parsed.
1004  */
1005 static int __init omap2_clk_arch_init(void)
1006 {
1007         if (!mpurate)
1008                 return -EINVAL;
1009
1010         if (omap2_select_table_rate(&virt_prcm_set, mpurate))
1011                 printk(KERN_ERR "Could not find matching MPU rate\n");
1012
1013         propagate_rate(&osc_ck);                /* update main root fast */
1014         propagate_rate(&func_32k_ck);           /* update main root slow */
1015
1016         printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL/MPU): "
1017                "%ld.%01ld/%ld/%ld MHz\n",
1018                (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
1019                (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
1020
1021         return 0;
1022 }
1023 arch_initcall(omap2_clk_arch_init);
1024
1025 int __init omap2_clk_init(void)
1026 {
1027         struct prcm_config *prcm;
1028         struct clk ** clkp;
1029         u32 clkrate;
1030
1031         clk_init(&omap2_clk_functions);
1032         omap2_get_crystal_rate(&osc_ck, &sys_ck);
1033
1034         for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
1035              clkp++) {
1036
1037                 if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) {
1038                         clk_register(*clkp);
1039                         continue;
1040                 }
1041
1042                 if ((*clkp)->flags & CLOCK_IN_OMAP243X && cpu_is_omap2430()) {
1043                         clk_register(*clkp);
1044                         continue;
1045                 }
1046         }
1047
1048         /* Check the MPU rate set by bootloader */
1049         clkrate = omap2_get_dpll_rate(&dpll_ck);
1050         for (prcm = rate_table; prcm->mpu_speed; prcm++) {
1051                 if (prcm->xtal_speed != sys_ck.rate)
1052                         continue;
1053                 if (prcm->dpll_speed <= clkrate)
1054                          break;
1055         }
1056         curr_prcm_set = prcm;
1057
1058         propagate_rate(&osc_ck);                /* update main root fast */
1059         propagate_rate(&func_32k_ck);           /* update main root slow */
1060
1061         printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): "
1062                "%ld.%01ld/%ld/%ld MHz\n",
1063                (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
1064                (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
1065
1066         /*
1067          * Only enable those clocks we will need, let the drivers
1068          * enable other clocks as necessary
1069          */
1070         clk_enable(&sync_32k_ick);
1071         clk_enable(&omapctrl_ick);
1072         if (cpu_is_omap2430())
1073                 clk_enable(&sdrc_ick);
1074
1075         return 0;
1076 }