diff options
author | Paul Walmsley <paul@pwsan.com> | 2008-03-18 09:09:51 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2008-04-14 13:29:39 -0400 |
commit | 02e19a960a519224a74da4d190965201044c1583 (patch) | |
tree | ee4bda760efdd18c1c9860251ec69fcb02d75f18 /arch | |
parent | b045d0809871eae4341e60a1db2b7d31703d8175 (diff) |
ARM: OMAP2: Add 34xx clock code
This patch add 34xx clock code.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-omap2/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock34xx.c | 235 |
2 files changed, 236 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 2eabadc81083..2feb6870b735 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile | |||
@@ -11,6 +11,7 @@ obj-$(CONFIG_PM) += pm.o sleep.o | |||
11 | 11 | ||
12 | # Clock framework | 12 | # Clock framework |
13 | obj-$(CONFIG_ARCH_OMAP2) += clock24xx.o | 13 | obj-$(CONFIG_ARCH_OMAP2) += clock24xx.o |
14 | obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o | ||
14 | 15 | ||
15 | # Specific board support | 16 | # Specific board support |
16 | obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o | 17 | obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o |
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c new file mode 100644 index 000000000000..f6c82a333815 --- /dev/null +++ b/arch/arm/mach-omap2/clock34xx.c | |||
@@ -0,0 +1,235 @@ | |||
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/MPU): " | ||
216 | "%ld.%01ld/%ld/%ld MHz\n", | ||
217 | (osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10, | ||
218 | (core_ck.rate / 1000000), (dpll1_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 | ||