]>
Commit | Line | Data |
---|---|---|
f87fa62a CN |
1 | /* |
2 | * clock.c | |
3 | * | |
4 | * clocks for AM33XX based boards | |
5 | * | |
6 | * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License as | |
10 | * published by the Free Software Foundation; either version 2 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | */ | |
18 | ||
19 | #include <common.h> | |
20 | #include <asm/arch/cpu.h> | |
21 | #include <asm/arch/clock.h> | |
22 | #include <asm/arch/hardware.h> | |
23 | #include <asm/io.h> | |
24 | ||
25 | #define PRCM_MOD_EN 0x2 | |
26 | #define PRCM_FORCE_WAKEUP 0x2 | |
e79cd8eb | 27 | #define PRCM_FUNCTL 0x0 |
f87fa62a CN |
28 | |
29 | #define PRCM_EMIF_CLK_ACTIVITY BIT(2) | |
30 | #define PRCM_L3_GCLK_ACTIVITY BIT(4) | |
31 | ||
32 | #define PLL_BYPASS_MODE 0x4 | |
33 | #define ST_MN_BYPASS 0x00000100 | |
34 | #define ST_DPLL_CLK 0x00000001 | |
35 | #define CLK_SEL_MASK 0x7ffff | |
36 | #define CLK_DIV_MASK 0x1f | |
37 | #define CLK_DIV2_MASK 0x7f | |
38 | #define CLK_SEL_SHIFT 0x8 | |
39 | #define CLK_MODE_SEL 0x7 | |
40 | #define CLK_MODE_MASK 0xfffffff8 | |
41 | #define CLK_DIV_SEL 0xFFFFFFE0 | |
e79cd8eb | 42 | #define CPGMAC0_IDLE 0x30000 |
f87fa62a CN |
43 | |
44 | const struct cm_perpll *cmper = (struct cm_perpll *)CM_PER; | |
45 | const struct cm_wkuppll *cmwkup = (struct cm_wkuppll *)CM_WKUP; | |
46 | const struct cm_dpll *cmdpll = (struct cm_dpll *)CM_DPLL; | |
000820b5 | 47 | const struct cm_rtc *cmrtc = (struct cm_rtc *)CM_RTC; |
f87fa62a CN |
48 | |
49 | static void enable_interface_clocks(void) | |
50 | { | |
51 | /* Enable all the Interconnect Modules */ | |
52 | writel(PRCM_MOD_EN, &cmper->l3clkctrl); | |
53 | while (readl(&cmper->l3clkctrl) != PRCM_MOD_EN) | |
54 | ; | |
55 | ||
56 | writel(PRCM_MOD_EN, &cmper->l4lsclkctrl); | |
57 | while (readl(&cmper->l4lsclkctrl) != PRCM_MOD_EN) | |
58 | ; | |
59 | ||
60 | writel(PRCM_MOD_EN, &cmper->l4fwclkctrl); | |
61 | while (readl(&cmper->l4fwclkctrl) != PRCM_MOD_EN) | |
62 | ; | |
63 | ||
64 | writel(PRCM_MOD_EN, &cmwkup->wkl4wkclkctrl); | |
65 | while (readl(&cmwkup->wkl4wkclkctrl) != PRCM_MOD_EN) | |
66 | ; | |
67 | ||
68 | writel(PRCM_MOD_EN, &cmper->l3instrclkctrl); | |
69 | while (readl(&cmper->l3instrclkctrl) != PRCM_MOD_EN) | |
70 | ; | |
71 | ||
72 | writel(PRCM_MOD_EN, &cmper->l4hsclkctrl); | |
73 | while (readl(&cmper->l4hsclkctrl) != PRCM_MOD_EN) | |
a438c756 TR |
74 | ; |
75 | ||
76 | writel(PRCM_MOD_EN, &cmwkup->wkgpio0clkctrl); | |
77 | while (readl(&cmwkup->wkgpio0clkctrl) != PRCM_MOD_EN) | |
f87fa62a CN |
78 | ; |
79 | } | |
80 | ||
81 | /* | |
82 | * Force power domain wake up transition | |
83 | * Ensure that the corresponding interface clock is active before | |
84 | * using the peripheral | |
85 | */ | |
86 | static void power_domain_wkup_transition(void) | |
87 | { | |
88 | writel(PRCM_FORCE_WAKEUP, &cmper->l3clkstctrl); | |
89 | writel(PRCM_FORCE_WAKEUP, &cmper->l4lsclkstctrl); | |
90 | writel(PRCM_FORCE_WAKEUP, &cmwkup->wkclkstctrl); | |
91 | writel(PRCM_FORCE_WAKEUP, &cmper->l4fwclkstctrl); | |
92 | writel(PRCM_FORCE_WAKEUP, &cmper->l3sclkstctrl); | |
93 | } | |
94 | ||
95 | /* | |
96 | * Enable the peripheral clock for required peripherals | |
97 | */ | |
98 | static void enable_per_clocks(void) | |
99 | { | |
100 | /* Enable the control module though RBL would have done it*/ | |
101 | writel(PRCM_MOD_EN, &cmwkup->wkctrlclkctrl); | |
102 | while (readl(&cmwkup->wkctrlclkctrl) != PRCM_MOD_EN) | |
103 | ; | |
104 | ||
105 | /* Enable the module clock */ | |
106 | writel(PRCM_MOD_EN, &cmper->timer2clkctrl); | |
107 | while (readl(&cmper->timer2clkctrl) != PRCM_MOD_EN) | |
108 | ; | |
109 | ||
fb072a3e CN |
110 | /* Select the Master osc 24 MHZ as Timer2 clock source */ |
111 | writel(0x1, &cmdpll->clktimer2clk); | |
112 | ||
f87fa62a CN |
113 | /* UART0 */ |
114 | writel(PRCM_MOD_EN, &cmwkup->wkup_uart0ctrl); | |
115 | while (readl(&cmwkup->wkup_uart0ctrl) != PRCM_MOD_EN) | |
116 | ; | |
876bdd6d | 117 | |
25164218 AB |
118 | /* UART1 */ |
119 | #ifdef CONFIG_SERIAL2 | |
120 | writel(PRCM_MOD_EN, &cmper->uart1clkctrl); | |
121 | while (readl(&cmper->uart1clkctrl) != PRCM_MOD_EN) | |
122 | ; | |
123 | #endif /* CONFIG_SERIAL2 */ | |
124 | ||
125 | /* UART2 */ | |
126 | #ifdef CONFIG_SERIAL3 | |
127 | writel(PRCM_MOD_EN, &cmper->uart2clkctrl); | |
128 | while (readl(&cmper->uart2clkctrl) != PRCM_MOD_EN) | |
129 | ; | |
130 | #endif /* CONFIG_SERIAL3 */ | |
131 | ||
132 | /* UART3 */ | |
133 | #ifdef CONFIG_SERIAL4 | |
134 | writel(PRCM_MOD_EN, &cmper->uart3clkctrl); | |
135 | while (readl(&cmper->uart3clkctrl) != PRCM_MOD_EN) | |
136 | ; | |
137 | #endif /* CONFIG_SERIAL4 */ | |
138 | ||
139 | /* UART4 */ | |
140 | #ifdef CONFIG_SERIAL5 | |
141 | writel(PRCM_MOD_EN, &cmper->uart4clkctrl); | |
142 | while (readl(&cmper->uart4clkctrl) != PRCM_MOD_EN) | |
143 | ; | |
144 | #endif /* CONFIG_SERIAL5 */ | |
145 | ||
146 | /* UART5 */ | |
147 | #ifdef CONFIG_SERIAL6 | |
148 | writel(PRCM_MOD_EN, &cmper->uart5clkctrl); | |
149 | while (readl(&cmper->uart5clkctrl) != PRCM_MOD_EN) | |
150 | ; | |
151 | #endif /* CONFIG_SERIAL6 */ | |
152 | ||
876bdd6d CN |
153 | /* MMC0*/ |
154 | writel(PRCM_MOD_EN, &cmper->mmc0clkctrl); | |
155 | while (readl(&cmper->mmc0clkctrl) != PRCM_MOD_EN) | |
156 | ; | |
b4116ede PR |
157 | |
158 | /* i2c0 */ | |
159 | writel(PRCM_MOD_EN, &cmwkup->wkup_i2c0ctrl); | |
160 | while (readl(&cmwkup->wkup_i2c0ctrl) != PRCM_MOD_EN) | |
161 | ; | |
3b97152b SS |
162 | |
163 | /* gpio1 module */ | |
164 | writel(PRCM_MOD_EN, &cmper->gpio1clkctrl); | |
165 | while (readl(&cmper->gpio1clkctrl) != PRCM_MOD_EN) | |
166 | ; | |
167 | ||
168 | /* gpio2 module */ | |
169 | writel(PRCM_MOD_EN, &cmper->gpio2clkctrl); | |
170 | while (readl(&cmper->gpio2clkctrl) != PRCM_MOD_EN) | |
171 | ; | |
172 | ||
173 | /* gpio3 module */ | |
174 | writel(PRCM_MOD_EN, &cmper->gpio3clkctrl); | |
175 | while (readl(&cmper->gpio3clkctrl) != PRCM_MOD_EN) | |
176 | ; | |
d3decdeb SS |
177 | |
178 | /* i2c1 */ | |
179 | writel(PRCM_MOD_EN, &cmper->i2c1clkctrl); | |
180 | while (readl(&cmper->i2c1clkctrl) != PRCM_MOD_EN) | |
181 | ; | |
e79cd8eb CN |
182 | |
183 | /* Ethernet */ | |
184 | writel(PRCM_MOD_EN, &cmper->cpgmac0clkctrl); | |
185 | while ((readl(&cmper->cpgmac0clkctrl) & CPGMAC0_IDLE) != PRCM_FUNCTL) | |
186 | ; | |
4c0620bf TR |
187 | |
188 | /* spi0 */ | |
189 | writel(PRCM_MOD_EN, &cmper->spi0clkctrl); | |
190 | while (readl(&cmper->spi0clkctrl) != PRCM_MOD_EN) | |
191 | ; | |
000820b5 VH |
192 | |
193 | /* RTC */ | |
194 | writel(PRCM_MOD_EN, &cmrtc->rtcclkctrl); | |
195 | while (readl(&cmrtc->rtcclkctrl) != PRCM_MOD_EN) | |
196 | ; | |
f87fa62a CN |
197 | } |
198 | ||
199 | static void mpu_pll_config(void) | |
200 | { | |
201 | u32 clkmode, clksel, div_m2; | |
202 | ||
203 | clkmode = readl(&cmwkup->clkmoddpllmpu); | |
204 | clksel = readl(&cmwkup->clkseldpllmpu); | |
205 | div_m2 = readl(&cmwkup->divm2dpllmpu); | |
206 | ||
207 | /* Set the PLL to bypass Mode */ | |
208 | writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllmpu); | |
209 | while (readl(&cmwkup->idlestdpllmpu) != ST_MN_BYPASS) | |
210 | ; | |
211 | ||
212 | clksel = clksel & (~CLK_SEL_MASK); | |
213 | clksel = clksel | ((MPUPLL_M << CLK_SEL_SHIFT) | MPUPLL_N); | |
214 | writel(clksel, &cmwkup->clkseldpllmpu); | |
215 | ||
216 | div_m2 = div_m2 & ~CLK_DIV_MASK; | |
217 | div_m2 = div_m2 | MPUPLL_M2; | |
218 | writel(div_m2, &cmwkup->divm2dpllmpu); | |
219 | ||
220 | clkmode = clkmode | CLK_MODE_SEL; | |
221 | writel(clkmode, &cmwkup->clkmoddpllmpu); | |
222 | ||
223 | while (readl(&cmwkup->idlestdpllmpu) != ST_DPLL_CLK) | |
224 | ; | |
225 | } | |
226 | ||
227 | static void core_pll_config(void) | |
228 | { | |
229 | u32 clkmode, clksel, div_m4, div_m5, div_m6; | |
230 | ||
231 | clkmode = readl(&cmwkup->clkmoddpllcore); | |
232 | clksel = readl(&cmwkup->clkseldpllcore); | |
233 | div_m4 = readl(&cmwkup->divm4dpllcore); | |
234 | div_m5 = readl(&cmwkup->divm5dpllcore); | |
235 | div_m6 = readl(&cmwkup->divm6dpllcore); | |
236 | ||
237 | /* Set the PLL to bypass Mode */ | |
238 | writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllcore); | |
239 | ||
240 | while (readl(&cmwkup->idlestdpllcore) != ST_MN_BYPASS) | |
241 | ; | |
242 | ||
243 | clksel = clksel & (~CLK_SEL_MASK); | |
244 | clksel = clksel | ((COREPLL_M << CLK_SEL_SHIFT) | COREPLL_N); | |
245 | writel(clksel, &cmwkup->clkseldpllcore); | |
246 | ||
247 | div_m4 = div_m4 & ~CLK_DIV_MASK; | |
248 | div_m4 = div_m4 | COREPLL_M4; | |
249 | writel(div_m4, &cmwkup->divm4dpllcore); | |
250 | ||
251 | div_m5 = div_m5 & ~CLK_DIV_MASK; | |
252 | div_m5 = div_m5 | COREPLL_M5; | |
253 | writel(div_m5, &cmwkup->divm5dpllcore); | |
254 | ||
255 | div_m6 = div_m6 & ~CLK_DIV_MASK; | |
256 | div_m6 = div_m6 | COREPLL_M6; | |
257 | writel(div_m6, &cmwkup->divm6dpllcore); | |
258 | ||
259 | clkmode = clkmode | CLK_MODE_SEL; | |
260 | writel(clkmode, &cmwkup->clkmoddpllcore); | |
261 | ||
262 | while (readl(&cmwkup->idlestdpllcore) != ST_DPLL_CLK) | |
263 | ; | |
264 | } | |
265 | ||
266 | static void per_pll_config(void) | |
267 | { | |
268 | u32 clkmode, clksel, div_m2; | |
269 | ||
270 | clkmode = readl(&cmwkup->clkmoddpllper); | |
271 | clksel = readl(&cmwkup->clkseldpllper); | |
272 | div_m2 = readl(&cmwkup->divm2dpllper); | |
273 | ||
274 | /* Set the PLL to bypass Mode */ | |
275 | writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllper); | |
276 | ||
277 | while (readl(&cmwkup->idlestdpllper) != ST_MN_BYPASS) | |
278 | ; | |
279 | ||
280 | clksel = clksel & (~CLK_SEL_MASK); | |
281 | clksel = clksel | ((PERPLL_M << CLK_SEL_SHIFT) | PERPLL_N); | |
282 | writel(clksel, &cmwkup->clkseldpllper); | |
283 | ||
284 | div_m2 = div_m2 & ~CLK_DIV2_MASK; | |
285 | div_m2 = div_m2 | PERPLL_M2; | |
286 | writel(div_m2, &cmwkup->divm2dpllper); | |
287 | ||
288 | clkmode = clkmode | CLK_MODE_SEL; | |
289 | writel(clkmode, &cmwkup->clkmoddpllper); | |
290 | ||
291 | while (readl(&cmwkup->idlestdpllper) != ST_DPLL_CLK) | |
292 | ; | |
293 | } | |
294 | ||
b971dfad | 295 | void ddr_pll_config(unsigned int ddrpll_m) |
f87fa62a CN |
296 | { |
297 | u32 clkmode, clksel, div_m2; | |
298 | ||
299 | clkmode = readl(&cmwkup->clkmoddpllddr); | |
300 | clksel = readl(&cmwkup->clkseldpllddr); | |
301 | div_m2 = readl(&cmwkup->divm2dpllddr); | |
302 | ||
303 | /* Set the PLL to bypass Mode */ | |
304 | clkmode = (clkmode & CLK_MODE_MASK) | PLL_BYPASS_MODE; | |
305 | writel(clkmode, &cmwkup->clkmoddpllddr); | |
306 | ||
307 | /* Wait till bypass mode is enabled */ | |
308 | while ((readl(&cmwkup->idlestdpllddr) & ST_MN_BYPASS) | |
309 | != ST_MN_BYPASS) | |
310 | ; | |
311 | ||
312 | clksel = clksel & (~CLK_SEL_MASK); | |
b971dfad | 313 | clksel = clksel | ((ddrpll_m << CLK_SEL_SHIFT) | DDRPLL_N); |
f87fa62a CN |
314 | writel(clksel, &cmwkup->clkseldpllddr); |
315 | ||
316 | div_m2 = div_m2 & CLK_DIV_SEL; | |
317 | div_m2 = div_m2 | DDRPLL_M2; | |
318 | writel(div_m2, &cmwkup->divm2dpllddr); | |
319 | ||
320 | clkmode = (clkmode & CLK_MODE_MASK) | CLK_MODE_SEL; | |
321 | writel(clkmode, &cmwkup->clkmoddpllddr); | |
322 | ||
323 | /* Wait till dpll is locked */ | |
324 | while ((readl(&cmwkup->idlestdpllddr) & ST_DPLL_CLK) != ST_DPLL_CLK) | |
325 | ; | |
326 | } | |
327 | ||
328 | void enable_emif_clocks(void) | |
329 | { | |
330 | /* Enable the EMIF_FW Functional clock */ | |
331 | writel(PRCM_MOD_EN, &cmper->emiffwclkctrl); | |
332 | /* Enable EMIF0 Clock */ | |
333 | writel(PRCM_MOD_EN, &cmper->emifclkctrl); | |
f87fa62a CN |
334 | /* Poll if module is functional */ |
335 | while ((readl(&cmper->emifclkctrl)) != PRCM_MOD_EN) | |
336 | ; | |
337 | } | |
338 | ||
339 | /* | |
340 | * Configure the PLL/PRCM for necessary peripherals | |
341 | */ | |
342 | void pll_init() | |
343 | { | |
344 | mpu_pll_config(); | |
345 | core_pll_config(); | |
346 | per_pll_config(); | |
f87fa62a CN |
347 | |
348 | /* Enable the required interconnect clocks */ | |
349 | enable_interface_clocks(); | |
350 | ||
351 | /* Power domain wake up transition */ | |
352 | power_domain_wkup_transition(); | |
353 | ||
354 | /* Enable the required peripherals */ | |
355 | enable_per_clocks(); | |
356 | } |