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