]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-omap2/clock24xx.c
OMAP2/3 clock: don't tinker with hardirqs when they are supposed to be disabled
[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/common.h>
32 #include <mach/clock.h>
33 #include <mach/sram.h>
34 #include <asm/div64.h>
35
36 #include <mach/sdrc.h>
37 #include "clock.h"
38 #include "clock24xx.h"
39 #include "prm.h"
40 #include "prm-regbits-24xx.h"
41 #include "cm.h"
42 #include "cm-regbits-24xx.h"
43
44 /* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
45 #define EN_APLL_STOPPED                 0
46 #define EN_APLL_LOCKED                  3
47
48 /* CM_CLKSEL1_PLL.APLLS_CLKIN options (24XX) */
49 #define APLLS_CLKIN_19_2MHZ             0
50 #define APLLS_CLKIN_13MHZ               2
51 #define APLLS_CLKIN_12MHZ               3
52
53 /* #define DOWN_VARIABLE_DPLL 1 */              /* Experimental */
54
55 static struct prcm_config *curr_prcm_set;
56 static struct clk *vclk;
57 static struct clk *sclk;
58
59 /*-------------------------------------------------------------------------
60  * Omap24xx specific clock functions
61  *-------------------------------------------------------------------------*/
62
63 /**
64  * omap2xxx_clk_get_core_rate - return the CORE_CLK rate
65  * @clk: pointer to the combined dpll_ck + core_ck (currently "dpll_ck")
66  * @parent_rate: rate of the parent of the dpll_ck
67  *
68  * Returns the CORE_CLK rate.  CORE_CLK can have one of three rate
69  * sources on OMAP2xxx: the DPLL CLKOUT rate, DPLL CLKOUTX2, or 32KHz
70  * (the latter is unusual).  This currently should be called with
71  * struct clk *dpll_ck, which is a composite clock of dpll_ck and
72  * core_ck.
73  */
74 static u32 omap2xxx_clk_get_core_rate(struct clk *clk,
75                                       unsigned long parent_rate)
76 {
77         long long core_clk;
78         u32 v;
79
80         core_clk = omap2_get_dpll_rate(clk, parent_rate);
81
82         v = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
83         v &= OMAP24XX_CORE_CLK_SRC_MASK;
84
85         if (v == CORE_CLK_SRC_32K)
86                 core_clk = 32768;
87         else
88                 core_clk *= v;
89
90         return core_clk;
91 }
92
93 static unsigned long omap2xxx_clk_find_oppset_by_mpurate(unsigned long mpu_speed,
94                                                          struct prcm_config **prcm)
95 {
96         unsigned long found_speed = 0;
97         struct prcm_config *p;
98
99         p = *prcm;
100
101         for (p = rate_table; p->mpu_speed; p++) {
102                 if (!(p->flags & cpu_mask))
103                         continue;
104
105                 if (p->xtal_speed != sys_ck.rate)
106                         continue;
107
108                 if (p->mpu_speed <= mpu_speed) {
109                         found_speed = p->mpu_speed;
110                         break;
111                 }
112         }
113
114         return found_speed;
115 }
116
117 static int omap2_enable_osc_ck(struct clk *clk)
118 {
119         prm_rmw_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK, 0,
120                         OMAP24XX_GR_MOD, OMAP24XX_PRCM_CLKSRC_CTRL_OFFSET);
121
122         return 0;
123 }
124
125 static void omap2_disable_osc_ck(struct clk *clk)
126 {
127         prm_rmw_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK, OMAP_AUTOEXTCLKMODE_MASK,
128                         OMAP24XX_GR_MOD, OMAP24XX_PRCM_CLKSRC_CTRL_OFFSET);
129 }
130
131 /* Enable an APLL if off */
132 static int omap2_clk_fixed_enable(struct clk *clk)
133 {
134         u32 cval, apll_mask;
135
136         apll_mask = EN_APLL_LOCKED << clk->enable_bit;
137
138         cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
139
140         if ((cval & apll_mask) == apll_mask)
141                 return 0;   /* apll already enabled */
142
143         cval &= ~apll_mask;
144         cval |= apll_mask;
145         cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
146
147         if (clk == &apll96_ck)
148                 cval = OMAP24XX_ST_96M_APLL;
149         else if (clk == &apll54_ck)
150                 cval = OMAP24XX_ST_54M_APLL;
151
152         omap2_wait_clock_ready(PLL_MOD, CM_IDLEST, cval, clk->name);
153
154         /*
155          * REVISIT: Should we return an error code if omap2_wait_clock_ready()
156          * fails?
157          */
158         return 0;
159 }
160
161 /* Stop APLL */
162 static void omap2_clk_fixed_disable(struct clk *clk)
163 {
164         u32 cval;
165
166         cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
167         cval &= ~(EN_APLL_LOCKED << clk->enable_bit);
168         cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
169 }
170
171 /*
172  * Uses the current prcm set to tell if a rate is valid.
173  * You can go slower, but not faster within a given rate set.
174  */
175 static long omap2_dpllcore_round_rate(unsigned long target_rate)
176 {
177         u32 high, low, core_clk_src;
178
179         core_clk_src = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
180         core_clk_src &= OMAP24XX_CORE_CLK_SRC_MASK;
181
182         if (core_clk_src == CORE_CLK_SRC_DPLL) {        /* DPLL clockout */
183                 high = curr_prcm_set->dpll_speed * 2;
184                 low = curr_prcm_set->dpll_speed;
185         } else {                                /* DPLL clockout x 2 */
186                 high = curr_prcm_set->dpll_speed;
187                 low = curr_prcm_set->dpll_speed / 2;
188         }
189
190 #ifdef DOWN_VARIABLE_DPLL
191         if (target_rate > high)
192                 return high;
193         else
194                 return target_rate;
195 #else
196         if (target_rate > low)
197                 return high;
198         else
199                 return low;
200 #endif
201
202 }
203
204 static void omap2_dpllcore_recalc(struct clk *clk, unsigned long parent_rate,
205                                   u8 rate_storage)
206 {
207         unsigned long rate;
208
209         rate = omap2xxx_clk_get_core_rate(clk, parent_rate);
210
211         if (rate_storage == CURRENT_RATE)
212                 clk->rate = rate;
213         else if (rate_storage == TEMP_RATE)
214                 clk->temp_rate = rate;
215 }
216
217 static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
218 {
219         u32 cur_rate, low, mult, div, valid_rate, done_rate;
220         u32 bypass = 0;
221         struct prcm_config tmpset;
222         const struct dpll_data *dd;
223
224         cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck, dpll_ck.parent->rate);
225         mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
226         mult &= OMAP24XX_CORE_CLK_SRC_MASK;
227
228         if ((rate == (cur_rate / 2)) && (mult == 2)) {
229                 omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
230         } else if ((rate == (cur_rate * 2)) && (mult == 1)) {
231                 omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
232         } else if (rate != cur_rate) {
233                 valid_rate = omap2_dpllcore_round_rate(rate);
234                 if (valid_rate != rate)
235                         return -EINVAL;
236
237                 if (mult == 1)
238                         low = curr_prcm_set->dpll_speed;
239                 else
240                         low = curr_prcm_set->dpll_speed / 2;
241
242                 dd = clk->dpll_data;
243                 if (!dd)
244                         return -EINVAL;
245
246                 tmpset.cm_clksel1_pll = cm_read_mod_reg(clk->prcm_mod,
247                                                         dd->mult_div1_reg);
248                 tmpset.cm_clksel1_pll &= ~(dd->mult_mask |
249                                            dd->div1_mask);
250                 div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
251                 tmpset.cm_clksel2_pll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
252                 tmpset.cm_clksel2_pll &= ~OMAP24XX_CORE_CLK_SRC_MASK;
253                 if (rate > low) {
254                         tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL_X2;
255                         mult = ((rate / 2) / 1000000);
256                         done_rate = CORE_CLK_SRC_DPLL_X2;
257                 } else {
258                         tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL;
259                         mult = (rate / 1000000);
260                         done_rate = CORE_CLK_SRC_DPLL;
261                 }
262                 tmpset.cm_clksel1_pll |= (div << __ffs(dd->mult_mask));
263                 tmpset.cm_clksel1_pll |= (mult << __ffs(dd->div1_mask));
264
265                 /* Worst case */
266                 tmpset.base_sdrc_rfr = SDRC_RFR_CTRL_BYPASS;
267
268                 if (rate == curr_prcm_set->xtal_speed)  /* If asking for 1-1 */
269                         bypass = 1;
270
271                 /* For omap2xxx_sdrc_init_params() */
272                 omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
273
274                 /* Force dll lock mode */
275                 omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
276                                bypass);
277
278                 /* Errata: ret dll entry state */
279                 omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
280                 omap2xxx_sdrc_reprogram(done_rate, 0);
281         }
282
283         return 0;
284 }
285
286 /**
287  * omap2_table_mpu_recalc - just return the MPU speed
288  * @clk: virt_prcm_set struct clk
289  *
290  * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
291  */
292 static void omap2_table_mpu_recalc(struct clk *clk, unsigned long parent_rate,
293                                    u8 rate_storage)
294 {
295         struct prcm_config *prcm;
296         unsigned long mpurate;
297
298         mpurate = omap2xxx_clk_find_oppset_by_mpurate(parent_rate, &prcm);
299
300         if (rate_storage == CURRENT_RATE)
301                 clk->rate = mpurate;
302         else if (rate_storage == TEMP_RATE)
303                 clk->temp_rate = mpurate;
304 }
305
306 /*
307  * Look for a rate equal or less than the target rate given a configuration set.
308  *
309  * What's not entirely clear is "which" field represents the key field.
310  * Some might argue L3-DDR, others ARM, others IVA. This code is simple and
311  * just uses the ARM rates.
312  */
313 static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate)
314 {
315         struct prcm_config *ptr;
316         long highest_rate;
317
318         if (clk != &virt_prcm_set)
319                 return -EINVAL;
320
321         highest_rate = -EINVAL;
322
323         for (ptr = rate_table; ptr->mpu_speed; ptr++) {
324                 if (!(ptr->flags & cpu_mask))
325                         continue;
326                 if (ptr->xtal_speed != sys_ck.rate)
327                         continue;
328
329                 highest_rate = ptr->mpu_speed;
330
331                 /* Can check only after xtal frequency check */
332                 if (ptr->mpu_speed <= rate)
333                         break;
334         }
335         return highest_rate;
336 }
337
338 /* Sets basic clocks based on the specified rate */
339 static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
340 {
341         u32 cur_rate, done_rate, bypass = 0, tmp;
342         struct prcm_config *prcm;
343         unsigned long flags, found_speed;
344
345         if (clk != &virt_prcm_set)
346                 return -EINVAL;
347
348         found_speed = omap2xxx_clk_find_oppset_by_mpurate(rate, &prcm);
349         if (!found_speed) {
350                 printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
351                        rate / 1000000);
352                 return -EINVAL;
353         }
354
355         curr_prcm_set = prcm;
356         cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck, dpll_ck.parent->rate);
357
358         if (prcm->dpll_speed == cur_rate / 2) {
359                 omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
360         } else if (prcm->dpll_speed == cur_rate * 2) {
361                 omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
362         } else if (prcm->dpll_speed != cur_rate) {
363                 local_irq_save(flags);
364
365                 if (prcm->dpll_speed == prcm->xtal_speed)
366                         bypass = 1;
367
368                 if ((prcm->cm_clksel2_pll & OMAP24XX_CORE_CLK_SRC_MASK) ==
369                     CORE_CLK_SRC_DPLL_X2)
370                         done_rate = CORE_CLK_SRC_DPLL_X2;
371                 else
372                         done_rate = CORE_CLK_SRC_DPLL;
373
374                 /* MPU divider */
375                 cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL);
376
377                 /* dsp + iva1 div(2420), iva2.1(2430) */
378                 cm_write_mod_reg(prcm->cm_clksel_dsp,
379                                  OMAP24XX_DSP_MOD, CM_CLKSEL);
380
381                 cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL);
382
383                 /* Major subsystem dividers */
384                 tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK;
385                 cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD,
386                                  CM_CLKSEL1);
387
388                 if (cpu_is_omap2430())
389                         cm_write_mod_reg(prcm->cm_clksel_mdm,
390                                          OMAP2430_MDM_MOD, CM_CLKSEL);
391
392                 /* x2 to enter omap2xxx_sdrc_init_params() */
393                 omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
394
395                 omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
396                                bypass);
397
398                 omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
399                 omap2xxx_sdrc_reprogram(done_rate, 0);
400
401                 local_irq_restore(flags);
402         }
403
404         return 0;
405 }
406
407 #ifdef CONFIG_CPU_FREQ
408 /*
409  * Walk PRCM rate table and fillout cpufreq freq_table
410  */
411 static struct cpufreq_frequency_table freq_table[ARRAY_SIZE(rate_table)];
412
413 void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
414 {
415         struct prcm_config *prcm;
416         int i = 0;
417
418         for (prcm = rate_table; prcm->mpu_speed; prcm++) {
419                 if (!(prcm->flags & cpu_mask))
420                         continue;
421                 if (prcm->xtal_speed != sys_ck.rate)
422                         continue;
423
424                 /* don't put bypass rates in table */
425                 if (prcm->dpll_speed == prcm->xtal_speed)
426                         continue;
427
428                 freq_table[i].index = i;
429                 freq_table[i].frequency = prcm->mpu_speed / 1000;
430                 i++;
431         }
432
433         if (i == 0) {
434                 printk(KERN_WARNING "%s: failed to initialize frequency "
435                        "table\n", __func__);
436                 return;
437         }
438
439         freq_table[i].index = i;
440         freq_table[i].frequency = CPUFREQ_TABLE_END;
441
442         *table = &freq_table[0];
443 }
444 #endif
445
446 static struct clk_functions omap2_clk_functions = {
447         .clk_register           = omap2_clk_register,
448         .clk_enable             = omap2_clk_enable,
449         .clk_disable            = omap2_clk_disable,
450         .clk_round_rate         = omap2_clk_round_rate,
451         .clk_set_rate           = omap2_clk_set_rate,
452         .clk_set_parent         = omap2_clk_set_parent,
453         .clk_get_parent         = omap2_clk_get_parent,
454         .clk_disable_unused     = omap2_clk_disable_unused,
455 #ifdef  CONFIG_CPU_FREQ
456         .clk_init_cpufreq_table = omap2_clk_init_cpufreq_table,
457 #endif
458 };
459
460 static u32 omap2_get_apll_clkin(void)
461 {
462         u32 aplls, srate = 0;
463
464         aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
465         aplls &= OMAP24XX_APLLS_CLKIN_MASK;
466         aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT;
467
468         if (aplls == APLLS_CLKIN_19_2MHZ)
469                 srate = 19200000;
470         else if (aplls == APLLS_CLKIN_13MHZ)
471                 srate = 13000000;
472         else if (aplls == APLLS_CLKIN_12MHZ)
473                 srate = 12000000;
474
475         return srate;
476 }
477
478 static u32 omap2_get_sysclkdiv(void)
479 {
480         u32 div;
481
482         div = prm_read_mod_reg(OMAP24XX_GR_MOD,
483                                 OMAP24XX_PRCM_CLKSRC_CTRL_OFFSET);
484         div &= OMAP_SYSCLKDIV_MASK;
485         div >>= OMAP_SYSCLKDIV_SHIFT;
486
487         return div;
488 }
489
490 static void omap2_osc_clk_recalc(struct clk *clk, unsigned long parent_rate,
491                                  u8 rate_storage)
492 {
493         unsigned long rate;
494
495         /* XXX osc_ck on 2xxx currently is parentless */
496         rate = omap2_get_apll_clkin() * omap2_get_sysclkdiv();
497
498         if (rate_storage == CURRENT_RATE)
499                 clk->rate = rate;
500         else if (rate_storage == TEMP_RATE)
501                 clk->temp_rate = rate;
502 }
503
504 static void omap2_sys_clk_recalc(struct clk *clk, unsigned long parent_rate,
505                                  u8 rate_storage)
506 {
507         unsigned long rate;
508
509         rate = parent_rate / omap2_get_sysclkdiv();
510
511         if (rate_storage == CURRENT_RATE)
512                 clk->rate = rate;
513         else if (rate_storage == TEMP_RATE)
514                 clk->temp_rate = rate;
515 }
516
517 /*
518  * Set clocks for bypass mode for reboot to work.
519  */
520 void omap2_clk_prepare_for_reboot(void)
521 {
522         u32 rate;
523
524         if (vclk == NULL || sclk == NULL)
525                 return;
526
527         rate = clk_get_rate(sclk);
528         clk_set_rate(vclk, rate);
529 }
530
531 /*
532  * Switch the MPU rate if specified on cmdline.
533  * We cannot do this early until cmdline is parsed.
534  */
535 static int __init omap2_clk_arch_init(void)
536 {
537         if (!mpurate)
538                 return -EINVAL;
539
540         if (clk_set_rate(&virt_prcm_set, mpurate))
541                 printk(KERN_ERR "Could not find matching MPU rate\n");
542
543         recalculate_root_clocks();
544
545         printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL/MPU): "
546                "%ld.%01ld/%ld/%ld MHz\n",
547                (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
548                (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
549
550         return 0;
551 }
552 arch_initcall(omap2_clk_arch_init);
553
554 int __init omap2_clk_init(void)
555 {
556         struct prcm_config *prcm;
557         struct clk **clkp;
558         u32 clkrate;
559
560         if (cpu_is_omap242x())
561                 cpu_mask = RATE_IN_242X;
562         else if (cpu_is_omap2430())
563                 cpu_mask = RATE_IN_243X;
564
565         clk_init(&omap2_clk_functions);
566
567         omap2_osc_clk_recalc(&osc_ck, 0, CURRENT_RATE);
568         omap2_sys_clk_recalc(&sys_ck, sys_ck.parent->rate, CURRENT_RATE);
569
570         for (clkp = onchip_24xx_clks;
571              clkp < onchip_24xx_clks + ARRAY_SIZE(onchip_24xx_clks);
572              clkp++) {
573
574                 if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) {
575                         clk_register(*clkp);
576                         continue;
577                 }
578
579                 if ((*clkp)->flags & CLOCK_IN_OMAP243X && cpu_is_omap2430()) {
580                         clk_register(*clkp);
581                         continue;
582                 }
583         }
584
585         /* Check the MPU rate set by bootloader */
586         clkrate = omap2xxx_clk_get_core_rate(&dpll_ck, dpll_ck.parent->rate);
587         for (prcm = rate_table; prcm->mpu_speed; prcm++) {
588                 if (!(prcm->flags & cpu_mask))
589                         continue;
590                 if (prcm->xtal_speed != sys_ck.rate)
591                         continue;
592                 if (prcm->dpll_speed <= clkrate)
593                          break;
594         }
595         curr_prcm_set = prcm;
596
597         recalculate_root_clocks();
598
599         printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): "
600                "%ld.%01ld/%ld/%ld MHz\n",
601                (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
602                (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
603
604         /*
605          * Only enable those clocks we will need, let the drivers
606          * enable other clocks as necessary
607          */
608         clk_enable_init_clocks();
609
610         /* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
611         vclk = clk_get(NULL, "virt_prcm_set");
612         sclk = clk_get(NULL, "sys_ck");
613
614         return 0;
615 }