]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-omap2/clock24xx.c
[ARM] omap: move propagate_rate() calls into generic omap clock code
[linux-2.6-omap-h63xx.git] / arch / arm / mach-omap2 / clock24xx.c
1 /*
2  *  linux/arch/arm/mach-omap2/clock.c
3  *
4  *  Copyright (C) 2005-2008 Texas Instruments, Inc.
5  *  Copyright (C) 2004-2008 Nokia Corporation
6  *
7  *  Contacts:
8  *  Richard Woodruff <r-woodruff2@ti.com>
9  *  Paul Walmsley
10  *
11  *  Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
12  *  Gordon McNutt and RidgeRun, Inc.
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 #undef DEBUG
19
20 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/device.h>
23 #include <linux/list.h>
24 #include <linux/errno.h>
25 #include <linux/delay.h>
26 #include <linux/clk.h>
27 #include <linux/io.h>
28 #include <linux/cpufreq.h>
29 #include <linux/bitops.h>
30
31 #include <mach/clock.h>
32 #include <mach/sram.h>
33 #include <asm/div64.h>
34
35 #include "memory.h"
36 #include "clock.h"
37 #include "prm.h"
38 #include "prm-regbits-24xx.h"
39 #include "cm.h"
40 #include "cm-regbits-24xx.h"
41
42 static const struct clkops clkops_oscck;
43 static const struct clkops clkops_fixed;
44
45 #include "clock24xx.h"
46
47 /* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
48 #define EN_APLL_STOPPED                 0
49 #define EN_APLL_LOCKED                  3
50
51 /* CM_CLKSEL1_PLL.APLLS_CLKIN options (24XX) */
52 #define APLLS_CLKIN_19_2MHZ             0
53 #define APLLS_CLKIN_13MHZ               2
54 #define APLLS_CLKIN_12MHZ               3
55
56 /* #define DOWN_VARIABLE_DPLL 1 */              /* Experimental */
57
58 static struct prcm_config *curr_prcm_set;
59 static struct clk *vclk;
60 static struct clk *sclk;
61
62 /*-------------------------------------------------------------------------
63  * Omap24xx specific clock functions
64  *-------------------------------------------------------------------------*/
65
66 /* This actually returns the rate of core_ck, not dpll_ck. */
67 static u32 omap2_get_dpll_rate_24xx(struct clk *tclk)
68 {
69         long long dpll_clk;
70         u8 amult;
71
72         dpll_clk = omap2_get_dpll_rate(tclk);
73
74         amult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
75         amult &= OMAP24XX_CORE_CLK_SRC_MASK;
76         dpll_clk *= amult;
77
78         return dpll_clk;
79 }
80
81 static int omap2_enable_osc_ck(struct clk *clk)
82 {
83         u32 pcc;
84
85         pcc = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL);
86
87         __raw_writel(pcc & ~OMAP_AUTOEXTCLKMODE_MASK,
88                       OMAP24XX_PRCM_CLKSRC_CTRL);
89
90         return 0;
91 }
92
93 static void omap2_disable_osc_ck(struct clk *clk)
94 {
95         u32 pcc;
96
97         pcc = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL);
98
99         __raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK,
100                       OMAP24XX_PRCM_CLKSRC_CTRL);
101 }
102
103 static const struct clkops clkops_oscck = {
104         .enable         = &omap2_enable_osc_ck,
105         .disable        = &omap2_disable_osc_ck,
106 };
107
108 #ifdef OLD_CK
109 /* Recalculate SYST_CLK */
110 static void omap2_sys_clk_recalc(struct clk * clk)
111 {
112         u32 div = PRCM_CLKSRC_CTRL;
113         div &= (1 << 7) | (1 << 6);     /* Test if ext clk divided by 1 or 2 */
114         div >>= clk->rate_offset;
115         clk->rate = (clk->parent->rate / div);
116         propagate_rate(clk);
117 }
118 #endif  /* OLD_CK */
119
120 /* Enable an APLL if off */
121 static int omap2_clk_fixed_enable(struct clk *clk)
122 {
123         u32 cval, apll_mask;
124
125         apll_mask = EN_APLL_LOCKED << clk->enable_bit;
126
127         cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
128
129         if ((cval & apll_mask) == apll_mask)
130                 return 0;   /* apll already enabled */
131
132         cval &= ~apll_mask;
133         cval |= apll_mask;
134         cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
135
136         if (clk == &apll96_ck)
137                 cval = OMAP24XX_ST_96M_APLL;
138         else if (clk == &apll54_ck)
139                 cval = OMAP24XX_ST_54M_APLL;
140
141         omap2_wait_clock_ready(OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), cval,
142                             clk->name);
143
144         /*
145          * REVISIT: Should we return an error code if omap2_wait_clock_ready()
146          * fails?
147          */
148         return 0;
149 }
150
151 /* Stop APLL */
152 static void omap2_clk_fixed_disable(struct clk *clk)
153 {
154         u32 cval;
155
156         cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
157         cval &= ~(EN_APLL_LOCKED << clk->enable_bit);
158         cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
159 }
160
161 static const struct clkops clkops_fixed = {
162         .enable         = &omap2_clk_fixed_enable,
163         .disable        = &omap2_clk_fixed_disable,
164 };
165
166 /*
167  * Uses the current prcm set to tell if a rate is valid.
168  * You can go slower, but not faster within a given rate set.
169  */
170 long omap2_dpllcore_round_rate(unsigned long target_rate)
171 {
172         u32 high, low, core_clk_src;
173
174         core_clk_src = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
175         core_clk_src &= OMAP24XX_CORE_CLK_SRC_MASK;
176
177         if (core_clk_src == CORE_CLK_SRC_DPLL) {        /* DPLL clockout */
178                 high = curr_prcm_set->dpll_speed * 2;
179                 low = curr_prcm_set->dpll_speed;
180         } else {                                /* DPLL clockout x 2 */
181                 high = curr_prcm_set->dpll_speed;
182                 low = curr_prcm_set->dpll_speed / 2;
183         }
184
185 #ifdef DOWN_VARIABLE_DPLL
186         if (target_rate > high)
187                 return high;
188         else
189                 return target_rate;
190 #else
191         if (target_rate > low)
192                 return high;
193         else
194                 return low;
195 #endif
196
197 }
198
199 static void omap2_dpllcore_recalc(struct clk *clk)
200 {
201         clk->rate = omap2_get_dpll_rate_24xx(clk);
202 }
203
204 static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
205 {
206         u32 cur_rate, low, mult, div, valid_rate, done_rate;
207         u32 bypass = 0;
208         struct prcm_config tmpset;
209         const struct dpll_data *dd;
210         unsigned long flags;
211         int ret = -EINVAL;
212
213         local_irq_save(flags);
214         cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
215         mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
216         mult &= OMAP24XX_CORE_CLK_SRC_MASK;
217
218         if ((rate == (cur_rate / 2)) && (mult == 2)) {
219                 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
220         } else if ((rate == (cur_rate * 2)) && (mult == 1)) {
221                 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
222         } else if (rate != cur_rate) {
223                 valid_rate = omap2_dpllcore_round_rate(rate);
224                 if (valid_rate != rate)
225                         goto dpll_exit;
226
227                 if (mult == 1)
228                         low = curr_prcm_set->dpll_speed;
229                 else
230                         low = curr_prcm_set->dpll_speed / 2;
231
232                 dd = clk->dpll_data;
233                 if (!dd)
234                         goto dpll_exit;
235
236                 tmpset.cm_clksel1_pll = __raw_readl(dd->mult_div1_reg);
237                 tmpset.cm_clksel1_pll &= ~(dd->mult_mask |
238                                            dd->div1_mask);
239                 div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
240                 tmpset.cm_clksel2_pll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
241                 tmpset.cm_clksel2_pll &= ~OMAP24XX_CORE_CLK_SRC_MASK;
242                 if (rate > low) {
243                         tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL_X2;
244                         mult = ((rate / 2) / 1000000);
245                         done_rate = CORE_CLK_SRC_DPLL_X2;
246                 } else {
247                         tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL;
248                         mult = (rate / 1000000);
249                         done_rate = CORE_CLK_SRC_DPLL;
250                 }
251                 tmpset.cm_clksel1_pll |= (div << __ffs(dd->mult_mask));
252                 tmpset.cm_clksel1_pll |= (mult << __ffs(dd->div1_mask));
253
254                 /* Worst case */
255                 tmpset.base_sdrc_rfr = SDRC_RFR_CTRL_BYPASS;
256
257                 if (rate == curr_prcm_set->xtal_speed)  /* If asking for 1-1 */
258                         bypass = 1;
259
260                 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); /* For init_mem */
261
262                 /* Force dll lock mode */
263                 omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
264                                bypass);
265
266                 /* Errata: ret dll entry state */
267                 omap2_init_memory_params(omap2_dll_force_needed());
268                 omap2_reprogram_sdrc(done_rate, 0);
269         }
270         omap2_dpllcore_recalc(&dpll_ck);
271         ret = 0;
272
273 dpll_exit:
274         local_irq_restore(flags);
275         return(ret);
276 }
277
278 /**
279  * omap2_table_mpu_recalc - just return the MPU speed
280  * @clk: virt_prcm_set struct clk
281  *
282  * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
283  */
284 static void omap2_table_mpu_recalc(struct clk *clk)
285 {
286         clk->rate = curr_prcm_set->mpu_speed;
287 }
288
289 /*
290  * Look for a rate equal or less than the target rate given a configuration set.
291  *
292  * What's not entirely clear is "which" field represents the key field.
293  * Some might argue L3-DDR, others ARM, others IVA. This code is simple and
294  * just uses the ARM rates.
295  */
296 static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate)
297 {
298         struct prcm_config *ptr;
299         long highest_rate;
300
301         if (clk != &virt_prcm_set)
302                 return -EINVAL;
303
304         highest_rate = -EINVAL;
305
306         for (ptr = rate_table; ptr->mpu_speed; ptr++) {
307                 if (!(ptr->flags & cpu_mask))
308                         continue;
309                 if (ptr->xtal_speed != sys_ck.rate)
310                         continue;
311
312                 highest_rate = ptr->mpu_speed;
313
314                 /* Can check only after xtal frequency check */
315                 if (ptr->mpu_speed <= rate)
316                         break;
317         }
318         return highest_rate;
319 }
320
321 /* Sets basic clocks based on the specified rate */
322 static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
323 {
324         u32 cur_rate, done_rate, bypass = 0, tmp;
325         struct prcm_config *prcm;
326         unsigned long found_speed = 0;
327         unsigned long flags;
328
329         if (clk != &virt_prcm_set)
330                 return -EINVAL;
331
332         for (prcm = rate_table; prcm->mpu_speed; prcm++) {
333                 if (!(prcm->flags & cpu_mask))
334                         continue;
335
336                 if (prcm->xtal_speed != sys_ck.rate)
337                         continue;
338
339                 if (prcm->mpu_speed <= rate) {
340                         found_speed = prcm->mpu_speed;
341                         break;
342                 }
343         }
344
345         if (!found_speed) {
346                 printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
347                        rate / 1000000);
348                 return -EINVAL;
349         }
350
351         curr_prcm_set = prcm;
352         cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
353
354         if (prcm->dpll_speed == cur_rate / 2) {
355                 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
356         } else if (prcm->dpll_speed == cur_rate * 2) {
357                 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
358         } else if (prcm->dpll_speed != cur_rate) {
359                 local_irq_save(flags);
360
361                 if (prcm->dpll_speed == prcm->xtal_speed)
362                         bypass = 1;
363
364                 if ((prcm->cm_clksel2_pll & OMAP24XX_CORE_CLK_SRC_MASK) ==
365                     CORE_CLK_SRC_DPLL_X2)
366                         done_rate = CORE_CLK_SRC_DPLL_X2;
367                 else
368                         done_rate = CORE_CLK_SRC_DPLL;
369
370                 /* MPU divider */
371                 cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL);
372
373                 /* dsp + iva1 div(2420), iva2.1(2430) */
374                 cm_write_mod_reg(prcm->cm_clksel_dsp,
375                                  OMAP24XX_DSP_MOD, CM_CLKSEL);
376
377                 cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL);
378
379                 /* Major subsystem dividers */
380                 tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK;
381                 cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD, CM_CLKSEL1);
382                 if (cpu_is_omap2430())
383                         cm_write_mod_reg(prcm->cm_clksel_mdm,
384                                          OMAP2430_MDM_MOD, CM_CLKSEL);
385
386                 /* x2 to enter init_mem */
387                 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
388
389                 omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
390                                bypass);
391
392                 omap2_init_memory_params(omap2_dll_force_needed());
393                 omap2_reprogram_sdrc(done_rate, 0);
394
395                 local_irq_restore(flags);
396         }
397         omap2_dpllcore_recalc(&dpll_ck);
398
399         return 0;
400 }
401
402 static struct clk_functions omap2_clk_functions = {
403         .clk_enable             = omap2_clk_enable,
404         .clk_disable            = omap2_clk_disable,
405         .clk_round_rate         = omap2_clk_round_rate,
406         .clk_set_rate           = omap2_clk_set_rate,
407         .clk_set_parent         = omap2_clk_set_parent,
408         .clk_disable_unused     = omap2_clk_disable_unused,
409 };
410
411 static u32 omap2_get_apll_clkin(void)
412 {
413         u32 aplls, sclk = 0;
414
415         aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
416         aplls &= OMAP24XX_APLLS_CLKIN_MASK;
417         aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT;
418
419         if (aplls == APLLS_CLKIN_19_2MHZ)
420                 sclk = 19200000;
421         else if (aplls == APLLS_CLKIN_13MHZ)
422                 sclk = 13000000;
423         else if (aplls == APLLS_CLKIN_12MHZ)
424                 sclk = 12000000;
425
426         return sclk;
427 }
428
429 static u32 omap2_get_sysclkdiv(void)
430 {
431         u32 div;
432
433         div = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL);
434         div &= OMAP_SYSCLKDIV_MASK;
435         div >>= OMAP_SYSCLKDIV_SHIFT;
436
437         return div;
438 }
439
440 static void omap2_osc_clk_recalc(struct clk *clk)
441 {
442         clk->rate = omap2_get_apll_clkin() * omap2_get_sysclkdiv();
443 }
444
445 static void omap2_sys_clk_recalc(struct clk *clk)
446 {
447         clk->rate = clk->parent->rate / omap2_get_sysclkdiv();
448 }
449
450 /*
451  * Set clocks for bypass mode for reboot to work.
452  */
453 void omap2_clk_prepare_for_reboot(void)
454 {
455         u32 rate;
456
457         if (vclk == NULL || sclk == NULL)
458                 return;
459
460         rate = clk_get_rate(sclk);
461         clk_set_rate(vclk, rate);
462 }
463
464 /*
465  * Switch the MPU rate if specified on cmdline.
466  * We cannot do this early until cmdline is parsed.
467  */
468 static int __init omap2_clk_arch_init(void)
469 {
470         if (!mpurate)
471                 return -EINVAL;
472
473         if (omap2_select_table_rate(&virt_prcm_set, mpurate))
474                 printk(KERN_ERR "Could not find matching MPU rate\n");
475
476         recalculate_root_clocks();
477
478         printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL/MPU): "
479                "%ld.%01ld/%ld/%ld MHz\n",
480                (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
481                (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
482
483         return 0;
484 }
485 arch_initcall(omap2_clk_arch_init);
486
487 int __init omap2_clk_init(void)
488 {
489         struct prcm_config *prcm;
490         struct clk **clkp;
491         u32 clkrate;
492
493         if (cpu_is_omap242x())
494                 cpu_mask = RATE_IN_242X;
495         else if (cpu_is_omap2430())
496                 cpu_mask = RATE_IN_243X;
497
498         clk_init(&omap2_clk_functions);
499
500         omap2_osc_clk_recalc(&osc_ck);
501         propagate_rate(&osc_ck);
502         omap2_sys_clk_recalc(&sys_ck);
503         propagate_rate(&sys_ck);
504
505         for (clkp = onchip_24xx_clks;
506              clkp < onchip_24xx_clks + ARRAY_SIZE(onchip_24xx_clks);
507              clkp++) {
508
509                 if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) {
510                         clk_register(*clkp);
511                         continue;
512                 }
513
514                 if ((*clkp)->flags & CLOCK_IN_OMAP243X && cpu_is_omap2430()) {
515                         clk_register(*clkp);
516                         continue;
517                 }
518         }
519
520         /* Check the MPU rate set by bootloader */
521         clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
522         for (prcm = rate_table; prcm->mpu_speed; prcm++) {
523                 if (!(prcm->flags & cpu_mask))
524                         continue;
525                 if (prcm->xtal_speed != sys_ck.rate)
526                         continue;
527                 if (prcm->dpll_speed <= clkrate)
528                          break;
529         }
530         curr_prcm_set = prcm;
531
532         recalculate_root_clocks();
533
534         printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): "
535                "%ld.%01ld/%ld/%ld MHz\n",
536                (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
537                (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
538
539         /*
540          * Only enable those clocks we will need, let the drivers
541          * enable other clocks as necessary
542          */
543         clk_enable_init_clocks();
544
545         /* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
546         vclk = clk_get(NULL, "virt_prcm_set");
547         sclk = clk_get(NULL, "sys_ck");
548
549         return 0;
550 }