Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6] / arch / arm / mach-omap2 / clock34xx.c
1 /*
2  * OMAP3-specific clock framework functions
3  *
4  * Copyright (C) 2007 Texas Instruments, Inc.
5  * Copyright (C) 2007 Nokia Corporation
6  *
7  * Written by Paul Walmsley
8  *
9  * Parts of this code are based on code written by
10  * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License version 2 as
14  * published by the Free Software Foundation.
15  */
16 #undef DEBUG
17
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/device.h>
21 #include <linux/list.h>
22 #include <linux/errno.h>
23 #include <linux/delay.h>
24 #include <linux/clk.h>
25 #include <linux/io.h>
26
27 #include <asm/arch/clock.h>
28 #include <asm/arch/sram.h>
29 #include <asm/div64.h>
30 #include <asm/bitops.h>
31
32 #include "memory.h"
33 #include "clock.h"
34 #include "clock34xx.h"
35 #include "prm.h"
36 #include "prm-regbits-34xx.h"
37 #include "cm.h"
38 #include "cm-regbits-34xx.h"
39
40 /* CM_CLKEN_PLL*.EN* bit values */
41 #define DPLL_LOCKED             0x7
42
43 /**
44  * omap3_dpll_recalc - recalculate DPLL rate
45  * @clk: DPLL struct clk
46  *
47  * Recalculate and propagate the DPLL rate.
48  */
49 static void omap3_dpll_recalc(struct clk *clk)
50 {
51         clk->rate = omap2_get_dpll_rate(clk);
52
53         propagate_rate(clk);
54 }
55
56 /**
57  * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate
58  * @clk: DPLL output struct clk
59  *
60  * Using parent clock DPLL data, look up DPLL state.  If locked, set our
61  * rate to the dpll_clk * 2; otherwise, just use dpll_clk.
62  */
63 static void omap3_clkoutx2_recalc(struct clk *clk)
64 {
65         const struct dpll_data *dd;
66         u32 v;
67         struct clk *pclk;
68
69         /* Walk up the parents of clk, looking for a DPLL */
70         pclk = clk->parent;
71         while (pclk && !pclk->dpll_data)
72                 pclk = pclk->parent;
73
74         /* clk does not have a DPLL as a parent? */
75         WARN_ON(!pclk);
76
77         dd = pclk->dpll_data;
78
79         WARN_ON(!dd->control_reg || !dd->enable_mask);
80
81         v = __raw_readl(dd->control_reg) & dd->enable_mask;
82         v >>= __ffs(dd->enable_mask);
83         if (v != DPLL_LOCKED)
84                 clk->rate = clk->parent->rate;
85         else
86                 clk->rate = clk->parent->rate * 2;
87
88         if (clk->flags & RATE_PROPAGATES)
89                 propagate_rate(clk);
90 }
91
92 /*
93  * As it is structured now, this will prevent an OMAP2/3 multiboot
94  * kernel from compiling.  This will need further attention.
95  */
96 #if defined(CONFIG_ARCH_OMAP3)
97
98 static struct clk_functions omap2_clk_functions = {
99         .clk_enable             = omap2_clk_enable,
100         .clk_disable            = omap2_clk_disable,
101         .clk_round_rate         = omap2_clk_round_rate,
102         .clk_set_rate           = omap2_clk_set_rate,
103         .clk_set_parent         = omap2_clk_set_parent,
104         .clk_disable_unused     = omap2_clk_disable_unused,
105 };
106
107 /*
108  * Set clocks for bypass mode for reboot to work.
109  */
110 void omap2_clk_prepare_for_reboot(void)
111 {
112         /* REVISIT: Not ready for 343x */
113 #if 0
114         u32 rate;
115
116         if (vclk == NULL || sclk == NULL)
117                 return;
118
119         rate = clk_get_rate(sclk);
120         clk_set_rate(vclk, rate);
121 #endif
122 }
123
124 /* REVISIT: Move this init stuff out into clock.c */
125
126 /*
127  * Switch the MPU rate if specified on cmdline.
128  * We cannot do this early until cmdline is parsed.
129  */
130 static int __init omap2_clk_arch_init(void)
131 {
132         if (!mpurate)
133                 return -EINVAL;
134
135         /* REVISIT: not yet ready for 343x */
136 #if 0
137         if (omap2_select_table_rate(&virt_prcm_set, mpurate))
138                 printk(KERN_ERR "Could not find matching MPU rate\n");
139 #endif
140
141         recalculate_root_clocks();
142
143         printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL3/MPU): "
144                "%ld.%01ld/%ld/%ld MHz\n",
145                (osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10,
146                (core_ck.rate / 1000000), (dpll1_fck.rate / 1000000)) ;
147
148         return 0;
149 }
150 arch_initcall(omap2_clk_arch_init);
151
152 int __init omap2_clk_init(void)
153 {
154         /* struct prcm_config *prcm; */
155         struct clk **clkp;
156         /* u32 clkrate; */
157         u32 cpu_clkflg;
158
159         /* REVISIT: Ultimately this will be used for multiboot */
160 #if 0
161         if (cpu_is_omap242x()) {
162                 cpu_mask = RATE_IN_242X;
163                 cpu_clkflg = CLOCK_IN_OMAP242X;
164                 clkp = onchip_24xx_clks;
165         } else if (cpu_is_omap2430()) {
166                 cpu_mask = RATE_IN_243X;
167                 cpu_clkflg = CLOCK_IN_OMAP243X;
168                 clkp = onchip_24xx_clks;
169         }
170 #endif
171         if (cpu_is_omap34xx()) {
172                 cpu_mask = RATE_IN_343X;
173                 cpu_clkflg = CLOCK_IN_OMAP343X;
174                 clkp = onchip_34xx_clks;
175
176                 /*
177                  * Update this if there are further clock changes between ES2
178                  * and production parts
179                  */
180                 if (is_sil_rev_equal_to(OMAP3430_REV_ES1_0)) {
181                         /* No 3430ES1-only rates exist, so no RATE_IN_3430ES1 */
182                         cpu_clkflg |= CLOCK_IN_OMAP3430ES1;
183                 } else {
184                         cpu_mask |= RATE_IN_3430ES2;
185                         cpu_clkflg |= CLOCK_IN_OMAP3430ES2;
186                 }
187         }
188
189         clk_init(&omap2_clk_functions);
190
191         for (clkp = onchip_34xx_clks;
192              clkp < onchip_34xx_clks + ARRAY_SIZE(onchip_34xx_clks);
193              clkp++) {
194                 if ((*clkp)->flags & cpu_clkflg)
195                         clk_register(*clkp);
196         }
197
198         /* REVISIT: Not yet ready for OMAP3 */
199 #if 0
200         /* Check the MPU rate set by bootloader */
201         clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
202         for (prcm = rate_table; prcm->mpu_speed; prcm++) {
203                 if (!(prcm->flags & cpu_mask))
204                         continue;
205                 if (prcm->xtal_speed != sys_ck.rate)
206                         continue;
207                 if (prcm->dpll_speed <= clkrate)
208                          break;
209         }
210         curr_prcm_set = prcm;
211 #endif
212
213         recalculate_root_clocks();
214
215         printk(KERN_INFO "Clocking rate (Crystal/DPLL/ARM core): "
216                "%ld.%01ld/%ld/%ld MHz\n",
217                (osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10,
218                (core_ck.rate / 1000000), (arm_fck.rate / 1000000));
219
220         /*
221          * Only enable those clocks we will need, let the drivers
222          * enable other clocks as necessary
223          */
224         clk_enable_init_clocks();
225
226         /* Avoid sleeping during omap2_clk_prepare_for_reboot() */
227         /* REVISIT: not yet ready for 343x */
228 #if 0
229         vclk = clk_get(NULL, "virt_prcm_set");
230         sclk = clk_get(NULL, "sys_ck");
231 #endif
232         return 0;
233 }
234
235 #endif