]>
Commit | Line | Data |
---|---|---|
3776801d A |
1 | /* |
2 | * | |
3 | * Clock initialization for OMAP4 | |
4 | * | |
5 | * (C) Copyright 2010 | |
6 | * Texas Instruments, <www.ti.com> | |
7 | * | |
8 | * Aneesh V <aneesh@ti.com> | |
9 | * | |
10 | * Based on previous work by: | |
11 | * Santosh Shilimkar <santosh.shilimkar@ti.com> | |
12 | * Rajendra Nayak <rnayak@ti.com> | |
13 | * | |
14 | * See file CREDITS for list of people who contributed to this | |
15 | * project. | |
16 | * | |
17 | * This program is free software; you can redistribute it and/or | |
18 | * modify it under the terms of the GNU General Public License as | |
19 | * published by the Free Software Foundation; either version 2 of | |
20 | * the License, or (at your option) any later version. | |
21 | * | |
22 | * This program is distributed in the hope that it will be useful, | |
23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
25 | * GNU General Public License for more details. | |
26 | * | |
27 | * You should have received a copy of the GNU General Public License | |
28 | * along with this program; if not, write to the Free Software | |
29 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
30 | * MA 02111-1307 USA | |
31 | */ | |
32 | #include <common.h> | |
33 | #include <asm/omap_common.h> | |
3b690ebb | 34 | #include <asm/gpio.h> |
3776801d A |
35 | #include <asm/arch/clocks.h> |
36 | #include <asm/arch/sys_proto.h> | |
37 | #include <asm/utils.h> | |
d506719f | 38 | #include <asm/omap_gpio.h> |
9ca8bfea | 39 | #include <asm/emif.h> |
3776801d A |
40 | |
41 | #ifndef CONFIG_SPL_BUILD | |
42 | /* | |
43 | * printing to console doesn't work unless | |
44 | * this code is executed from SPL | |
45 | */ | |
46 | #define printf(fmt, args...) | |
47 | #define puts(s) | |
48 | #endif | |
49 | ||
ee9447bf S |
50 | const u32 sys_clk_array[8] = { |
51 | 12000000, /* 12 MHz */ | |
52 | 13000000, /* 13 MHz */ | |
53 | 16800000, /* 16.8 MHz */ | |
54 | 19200000, /* 19.2 MHz */ | |
55 | 26000000, /* 26 MHz */ | |
56 | 27000000, /* 27 MHz */ | |
57 | 38400000, /* 38.4 MHz */ | |
58 | }; | |
59 | ||
3776801d A |
60 | static inline u32 __get_sys_clk_index(void) |
61 | { | |
62 | u32 ind; | |
63 | /* | |
64 | * For ES1 the ROM code calibration of sys clock is not reliable | |
65 | * due to hw issue. So, use hard-coded value. If this value is not | |
66 | * correct for any board over-ride this function in board file | |
67 | * From ES2.0 onwards you will get this information from | |
68 | * CM_SYS_CLKSEL | |
69 | */ | |
70 | if (omap_revision() == OMAP4430_ES1_0) | |
71 | ind = OMAP_SYS_CLK_IND_38_4_MHZ; | |
72 | else { | |
73 | /* SYS_CLKSEL - 1 to match the dpll param array indices */ | |
01b753ff | 74 | ind = (readl((*prcm)->cm_sys_clksel) & |
3776801d A |
75 | CM_SYS_CLKSEL_SYS_CLKSEL_MASK) - 1; |
76 | } | |
77 | return ind; | |
78 | } | |
79 | ||
80 | u32 get_sys_clk_index(void) | |
81 | __attribute__ ((weak, alias("__get_sys_clk_index"))); | |
82 | ||
83 | u32 get_sys_clk_freq(void) | |
84 | { | |
85 | u8 index = get_sys_clk_index(); | |
86 | return sys_clk_array[index]; | |
87 | } | |
88 | ||
ee9447bf S |
89 | void setup_post_dividers(u32 const base, const struct dpll_params *params) |
90 | { | |
91 | struct dpll_regs *const dpll_regs = (struct dpll_regs *)base; | |
92 | ||
93 | /* Setup post-dividers */ | |
94 | if (params->m2 >= 0) | |
95 | writel(params->m2, &dpll_regs->cm_div_m2_dpll); | |
96 | if (params->m3 >= 0) | |
97 | writel(params->m3, &dpll_regs->cm_div_m3_dpll); | |
98 | if (params->m4_h11 >= 0) | |
99 | writel(params->m4_h11, &dpll_regs->cm_div_m4_h11_dpll); | |
100 | if (params->m5_h12 >= 0) | |
101 | writel(params->m5_h12, &dpll_regs->cm_div_m5_h12_dpll); | |
102 | if (params->m6_h13 >= 0) | |
103 | writel(params->m6_h13, &dpll_regs->cm_div_m6_h13_dpll); | |
104 | if (params->m7_h14 >= 0) | |
105 | writel(params->m7_h14, &dpll_regs->cm_div_m7_h14_dpll); | |
106 | if (params->h22 >= 0) | |
107 | writel(params->h22, &dpll_regs->cm_div_h22_dpll); | |
108 | if (params->h23 >= 0) | |
109 | writel(params->h23, &dpll_regs->cm_div_h23_dpll); | |
110 | } | |
111 | ||
01b753ff | 112 | static inline void do_bypass_dpll(u32 const base) |
3776801d A |
113 | { |
114 | struct dpll_regs *dpll_regs = (struct dpll_regs *)base; | |
115 | ||
116 | clrsetbits_le32(&dpll_regs->cm_clkmode_dpll, | |
117 | CM_CLKMODE_DPLL_DPLL_EN_MASK, | |
118 | DPLL_EN_FAST_RELOCK_BYPASS << | |
119 | CM_CLKMODE_DPLL_EN_SHIFT); | |
120 | } | |
121 | ||
01b753ff | 122 | static inline void wait_for_bypass(u32 const base) |
3776801d A |
123 | { |
124 | struct dpll_regs *const dpll_regs = (struct dpll_regs *)base; | |
125 | ||
126 | if (!wait_on_value(ST_DPLL_CLK_MASK, 0, &dpll_regs->cm_idlest_dpll, | |
127 | LDELAY)) { | |
01b753ff | 128 | printf("Bypassing DPLL failed %x\n", base); |
3776801d A |
129 | } |
130 | } | |
131 | ||
01b753ff | 132 | static inline void do_lock_dpll(u32 const base) |
3776801d A |
133 | { |
134 | struct dpll_regs *const dpll_regs = (struct dpll_regs *)base; | |
135 | ||
136 | clrsetbits_le32(&dpll_regs->cm_clkmode_dpll, | |
137 | CM_CLKMODE_DPLL_DPLL_EN_MASK, | |
138 | DPLL_EN_LOCK << CM_CLKMODE_DPLL_EN_SHIFT); | |
139 | } | |
140 | ||
01b753ff | 141 | static inline void wait_for_lock(u32 const base) |
3776801d A |
142 | { |
143 | struct dpll_regs *const dpll_regs = (struct dpll_regs *)base; | |
144 | ||
145 | if (!wait_on_value(ST_DPLL_CLK_MASK, ST_DPLL_CLK_MASK, | |
146 | &dpll_regs->cm_idlest_dpll, LDELAY)) { | |
01b753ff | 147 | printf("DPLL locking failed for %x\n", base); |
3776801d A |
148 | hang(); |
149 | } | |
150 | } | |
151 | ||
01b753ff | 152 | inline u32 check_for_lock(u32 const base) |
78f455c0 S |
153 | { |
154 | struct dpll_regs *const dpll_regs = (struct dpll_regs *)base; | |
155 | u32 lock = readl(&dpll_regs->cm_idlest_dpll) & ST_DPLL_CLK_MASK; | |
156 | ||
157 | return lock; | |
158 | } | |
159 | ||
ee9447bf S |
160 | const struct dpll_params *get_mpu_dpll_params(struct dplls const *dpll_data) |
161 | { | |
162 | u32 sysclk_ind = get_sys_clk_index(); | |
163 | return &dpll_data->mpu[sysclk_ind]; | |
164 | } | |
165 | ||
166 | const struct dpll_params *get_core_dpll_params(struct dplls const *dpll_data) | |
167 | { | |
168 | u32 sysclk_ind = get_sys_clk_index(); | |
169 | return &dpll_data->core[sysclk_ind]; | |
170 | } | |
171 | ||
172 | const struct dpll_params *get_per_dpll_params(struct dplls const *dpll_data) | |
173 | { | |
174 | u32 sysclk_ind = get_sys_clk_index(); | |
175 | return &dpll_data->per[sysclk_ind]; | |
176 | } | |
177 | ||
178 | const struct dpll_params *get_iva_dpll_params(struct dplls const *dpll_data) | |
179 | { | |
180 | u32 sysclk_ind = get_sys_clk_index(); | |
181 | return &dpll_data->iva[sysclk_ind]; | |
182 | } | |
183 | ||
184 | const struct dpll_params *get_usb_dpll_params(struct dplls const *dpll_data) | |
185 | { | |
186 | u32 sysclk_ind = get_sys_clk_index(); | |
187 | return &dpll_data->usb[sysclk_ind]; | |
188 | } | |
189 | ||
190 | const struct dpll_params *get_abe_dpll_params(struct dplls const *dpll_data) | |
191 | { | |
192 | #ifdef CONFIG_SYS_OMAP_ABE_SYSCK | |
193 | u32 sysclk_ind = get_sys_clk_index(); | |
194 | return &dpll_data->abe[sysclk_ind]; | |
195 | #else | |
196 | return dpll_data->abe; | |
197 | #endif | |
198 | } | |
199 | ||
01b753ff | 200 | static void do_setup_dpll(u32 const base, const struct dpll_params *params, |
78f455c0 | 201 | u8 lock, char *dpll) |
3776801d | 202 | { |
78f455c0 | 203 | u32 temp, M, N; |
3776801d A |
204 | struct dpll_regs *const dpll_regs = (struct dpll_regs *)base; |
205 | ||
78f455c0 S |
206 | temp = readl(&dpll_regs->cm_clksel_dpll); |
207 | ||
208 | if (check_for_lock(base)) { | |
209 | /* | |
210 | * The Dpll has already been locked by rom code using CH. | |
211 | * Check if M,N are matching with Ideal nominal opp values. | |
212 | * If matches, skip the rest otherwise relock. | |
213 | */ | |
214 | M = (temp & CM_CLKSEL_DPLL_M_MASK) >> CM_CLKSEL_DPLL_M_SHIFT; | |
215 | N = (temp & CM_CLKSEL_DPLL_N_MASK) >> CM_CLKSEL_DPLL_N_SHIFT; | |
216 | if ((M != (params->m)) || (N != (params->n))) { | |
217 | debug("\n %s Dpll locked, but not for ideal M = %d," | |
218 | "N = %d values, current values are M = %d," | |
219 | "N= %d" , dpll, params->m, params->n, | |
220 | M, N); | |
221 | } else { | |
222 | /* Dpll locked with ideal values for nominal opps. */ | |
223 | debug("\n %s Dpll already locked with ideal" | |
224 | "nominal opp values", dpll); | |
225 | goto setup_post_dividers; | |
226 | } | |
227 | } | |
228 | ||
3776801d A |
229 | bypass_dpll(base); |
230 | ||
231 | /* Set M & N */ | |
3776801d A |
232 | temp &= ~CM_CLKSEL_DPLL_M_MASK; |
233 | temp |= (params->m << CM_CLKSEL_DPLL_M_SHIFT) & CM_CLKSEL_DPLL_M_MASK; | |
234 | ||
235 | temp &= ~CM_CLKSEL_DPLL_N_MASK; | |
236 | temp |= (params->n << CM_CLKSEL_DPLL_N_SHIFT) & CM_CLKSEL_DPLL_N_MASK; | |
237 | ||
238 | writel(temp, &dpll_regs->cm_clksel_dpll); | |
239 | ||
240 | /* Lock */ | |
241 | if (lock) | |
242 | do_lock_dpll(base); | |
243 | ||
78f455c0 | 244 | setup_post_dividers: |
2e5ba489 | 245 | setup_post_dividers(base, params); |
3776801d A |
246 | |
247 | /* Wait till the DPLL locks */ | |
248 | if (lock) | |
249 | wait_for_lock(base); | |
250 | } | |
251 | ||
2e5ba489 | 252 | u32 omap_ddr_clk(void) |
3776801d | 253 | { |
2e5ba489 | 254 | u32 ddr_clk, sys_clk_khz, omap_rev, divider; |
3776801d A |
255 | const struct dpll_params *core_dpll_params; |
256 | ||
2e5ba489 | 257 | omap_rev = omap_revision(); |
3776801d A |
258 | sys_clk_khz = get_sys_clk_freq() / 1000; |
259 | ||
ee9447bf | 260 | core_dpll_params = get_core_dpll_params(*dplls_data); |
3776801d A |
261 | |
262 | debug("sys_clk %d\n ", sys_clk_khz * 1000); | |
263 | ||
264 | /* Find Core DPLL locked frequency first */ | |
265 | ddr_clk = sys_clk_khz * 2 * core_dpll_params->m / | |
266 | (core_dpll_params->n + 1); | |
3776801d | 267 | |
2e5ba489 S |
268 | if (omap_rev < OMAP5430_ES1_0) { |
269 | /* | |
270 | * DDR frequency is PHY_ROOT_CLK/2 | |
271 | * PHY_ROOT_CLK = Fdpll/2/M2 | |
272 | */ | |
273 | divider = 4; | |
274 | } else { | |
275 | /* | |
276 | * DDR frequency is PHY_ROOT_CLK | |
277 | * PHY_ROOT_CLK = Fdpll/2/M2 | |
278 | */ | |
279 | divider = 2; | |
280 | } | |
281 | ||
282 | ddr_clk = ddr_clk / divider / core_dpll_params->m2; | |
3776801d A |
283 | ddr_clk *= 1000; /* convert to Hz */ |
284 | debug("ddr_clk %d\n ", ddr_clk); | |
285 | ||
286 | return ddr_clk; | |
287 | } | |
288 | ||
b4dc6442 A |
289 | /* |
290 | * Lock MPU dpll | |
291 | * | |
292 | * Resulting MPU frequencies: | |
293 | * 4430 ES1.0 : 600 MHz | |
294 | * 4430 ES2.x : 792 MHz (OPP Turbo) | |
295 | * 4460 : 920 MHz (OPP Turbo) - DCC disabled | |
296 | */ | |
297 | void configure_mpu_dpll(void) | |
298 | { | |
299 | const struct dpll_params *params; | |
300 | struct dpll_regs *mpu_dpll_regs; | |
2e5ba489 S |
301 | u32 omap_rev; |
302 | omap_rev = omap_revision(); | |
b4dc6442 | 303 | |
2e5ba489 S |
304 | /* |
305 | * DCC and clock divider settings for 4460. | |
306 | * DCC is required, if more than a certain frequency is required. | |
307 | * For, 4460 > 1GHZ. | |
308 | * 5430 > 1.4GHZ. | |
309 | */ | |
310 | if ((omap_rev >= OMAP4460_ES1_0) && (omap_rev < OMAP5430_ES1_0)) { | |
b4dc6442 | 311 | mpu_dpll_regs = |
01b753ff S |
312 | (struct dpll_regs *)((*prcm)->cm_clkmode_dpll_mpu); |
313 | bypass_dpll((*prcm)->cm_clkmode_dpll_mpu); | |
314 | clrbits_le32((*prcm)->cm_mpu_mpu_clkctrl, | |
b4dc6442 | 315 | MPU_CLKCTRL_CLKSEL_EMIF_DIV_MODE_MASK); |
01b753ff | 316 | setbits_le32((*prcm)->cm_mpu_mpu_clkctrl, |
b4dc6442 A |
317 | MPU_CLKCTRL_CLKSEL_ABE_DIV_MODE_MASK); |
318 | clrbits_le32(&mpu_dpll_regs->cm_clksel_dpll, | |
319 | CM_CLKSEL_DCC_EN_MASK); | |
320 | } | |
321 | ||
01b753ff | 322 | setbits_le32((*prcm)->cm_mpu_mpu_clkctrl, |
5f14d919 | 323 | MPU_CLKCTRL_CLKSEL_EMIF_DIV_MODE_MASK); |
01b753ff | 324 | setbits_le32((*prcm)->cm_mpu_mpu_clkctrl, |
5f14d919 S |
325 | MPU_CLKCTRL_CLKSEL_ABE_DIV_MODE_MASK); |
326 | ||
ee9447bf | 327 | params = get_mpu_dpll_params(*dplls_data); |
78f455c0 | 328 | |
01b753ff | 329 | do_setup_dpll((*prcm)->cm_clkmode_dpll_mpu, params, DPLL_LOCK, "mpu"); |
b4dc6442 A |
330 | debug("MPU DPLL locked\n"); |
331 | } | |
332 | ||
860004c1 G |
333 | #ifdef CONFIG_USB_EHCI_OMAP |
334 | static void setup_usb_dpll(void) | |
335 | { | |
336 | const struct dpll_params *params; | |
337 | u32 sys_clk_khz, sd_div, num, den; | |
338 | ||
339 | sys_clk_khz = get_sys_clk_freq() / 1000; | |
340 | /* | |
341 | * USB: | |
342 | * USB dpll is J-type. Need to set DPLL_SD_DIV for jitter correction | |
343 | * DPLL_SD_DIV = CEILING ([DPLL_MULT/(DPLL_DIV+1)]* CLKINP / 250) | |
344 | * - where CLKINP is sys_clk in MHz | |
345 | * Use CLKINP in KHz and adjust the denominator accordingly so | |
346 | * that we have enough accuracy and at the same time no overflow | |
347 | */ | |
ee9447bf | 348 | params = get_usb_dpll_params(*dplls_data); |
860004c1 G |
349 | num = params->m * sys_clk_khz; |
350 | den = (params->n + 1) * 250 * 1000; | |
351 | num += den - 1; | |
352 | sd_div = num / den; | |
01b753ff | 353 | clrsetbits_le32((*prcm)->cm_clksel_dpll_usb, |
860004c1 G |
354 | CM_CLKSEL_DPLL_DPLL_SD_DIV_MASK, |
355 | sd_div << CM_CLKSEL_DPLL_DPLL_SD_DIV_SHIFT); | |
356 | ||
357 | /* Now setup the dpll with the regular function */ | |
01b753ff | 358 | do_setup_dpll((*prcm)->cm_clkmode_dpll_usb, params, DPLL_LOCK, "usb"); |
860004c1 G |
359 | } |
360 | #endif | |
361 | ||
3776801d A |
362 | static void setup_dplls(void) |
363 | { | |
164a7507 | 364 | u32 temp; |
3776801d | 365 | const struct dpll_params *params; |
3776801d | 366 | |
164a7507 | 367 | debug("setup_dplls\n"); |
3776801d A |
368 | |
369 | /* CORE dpll */ | |
ee9447bf | 370 | params = get_core_dpll_params(*dplls_data); /* default - safest */ |
3776801d A |
371 | /* |
372 | * Do not lock the core DPLL now. Just set it up. | |
373 | * Core DPLL will be locked after setting up EMIF | |
374 | * using the FREQ_UPDATE method(freq_update_core()) | |
375 | */ | |
9ca8bfea | 376 | if (emif_sdram_type() == EMIF_SDRAM_TYPE_LPDDR2) |
01b753ff | 377 | do_setup_dpll((*prcm)->cm_clkmode_dpll_core, params, |
753bae8c LV |
378 | DPLL_NO_LOCK, "core"); |
379 | else | |
01b753ff | 380 | do_setup_dpll((*prcm)->cm_clkmode_dpll_core, params, |
753bae8c | 381 | DPLL_LOCK, "core"); |
3776801d A |
382 | /* Set the ratios for CORE_CLK, L3_CLK, L4_CLK */ |
383 | temp = (CLKSEL_CORE_X2_DIV_1 << CLKSEL_CORE_SHIFT) | | |
384 | (CLKSEL_L3_CORE_DIV_2 << CLKSEL_L3_SHIFT) | | |
385 | (CLKSEL_L4_L3_DIV_2 << CLKSEL_L4_SHIFT); | |
01b753ff | 386 | writel(temp, (*prcm)->cm_clksel_core); |
3776801d A |
387 | debug("Core DPLL configured\n"); |
388 | ||
389 | /* lock PER dpll */ | |
ee9447bf | 390 | params = get_per_dpll_params(*dplls_data); |
01b753ff | 391 | do_setup_dpll((*prcm)->cm_clkmode_dpll_per, |
78f455c0 | 392 | params, DPLL_LOCK, "per"); |
3776801d A |
393 | debug("PER DPLL locked\n"); |
394 | ||
395 | /* MPU dpll */ | |
b4dc6442 | 396 | configure_mpu_dpll(); |
860004c1 G |
397 | |
398 | #ifdef CONFIG_USB_EHCI_OMAP | |
399 | setup_usb_dpll(); | |
400 | #endif | |
3776801d A |
401 | } |
402 | ||
78f455c0 | 403 | #ifdef CONFIG_SYS_CLOCKS_ENABLE_ALL |
3776801d A |
404 | static void setup_non_essential_dplls(void) |
405 | { | |
27ac87d9 | 406 | u32 abe_ref_clk; |
3776801d A |
407 | const struct dpll_params *params; |
408 | ||
3776801d | 409 | /* IVA */ |
01b753ff | 410 | clrsetbits_le32((*prcm)->cm_bypclk_dpll_iva, |
3776801d A |
411 | CM_BYPCLK_DPLL_IVA_CLKSEL_MASK, DPLL_IVA_CLKSEL_CORE_X2_DIV_2); |
412 | ||
ee9447bf | 413 | params = get_iva_dpll_params(*dplls_data); |
01b753ff | 414 | do_setup_dpll((*prcm)->cm_clkmode_dpll_iva, params, DPLL_LOCK, "iva"); |
3776801d | 415 | |
2e5ba489 | 416 | /* Configure ABE dpll */ |
ee9447bf | 417 | params = get_abe_dpll_params(*dplls_data); |
2e5ba489 | 418 | #ifdef CONFIG_SYS_OMAP_ABE_SYSCK |
3776801d A |
419 | abe_ref_clk = CM_ABE_PLL_REF_CLKSEL_CLKSEL_SYSCLK; |
420 | #else | |
3776801d A |
421 | abe_ref_clk = CM_ABE_PLL_REF_CLKSEL_CLKSEL_32KCLK; |
422 | /* | |
423 | * We need to enable some additional options to achieve | |
424 | * 196.608MHz from 32768 Hz | |
425 | */ | |
01b753ff | 426 | setbits_le32((*prcm)->cm_clkmode_dpll_abe, |
3776801d A |
427 | CM_CLKMODE_DPLL_DRIFTGUARD_EN_MASK| |
428 | CM_CLKMODE_DPLL_RELOCK_RAMP_EN_MASK| | |
429 | CM_CLKMODE_DPLL_LPMODE_EN_MASK| | |
430 | CM_CLKMODE_DPLL_REGM4XEN_MASK); | |
431 | /* Spend 4 REFCLK cycles at each stage */ | |
01b753ff | 432 | clrsetbits_le32((*prcm)->cm_clkmode_dpll_abe, |
3776801d A |
433 | CM_CLKMODE_DPLL_RAMP_RATE_MASK, |
434 | 1 << CM_CLKMODE_DPLL_RAMP_RATE_SHIFT); | |
435 | #endif | |
436 | ||
437 | /* Select the right reference clk */ | |
01b753ff | 438 | clrsetbits_le32((*prcm)->cm_abe_pll_ref_clksel, |
3776801d A |
439 | CM_ABE_PLL_REF_CLKSEL_CLKSEL_MASK, |
440 | abe_ref_clk << CM_ABE_PLL_REF_CLKSEL_CLKSEL_SHIFT); | |
441 | /* Lock the dpll */ | |
01b753ff | 442 | do_setup_dpll((*prcm)->cm_clkmode_dpll_abe, params, DPLL_LOCK, "abe"); |
3776801d | 443 | } |
78f455c0 | 444 | #endif |
3776801d | 445 | |
3acb5534 | 446 | void do_scale_tps62361(int gpio, u32 reg, u32 volt_mv) |
d506719f | 447 | { |
a78274b2 | 448 | u32 step; |
3acb5534 NM |
449 | int ret = 0; |
450 | ||
451 | /* See if we can first get the GPIO if needed */ | |
452 | if (gpio >= 0) | |
453 | ret = gpio_request(gpio, "TPS62361_VSEL0_GPIO"); | |
454 | if (ret < 0) { | |
455 | printf("%s: gpio %d request failed %d\n", __func__, gpio, ret); | |
456 | gpio = -1; | |
457 | } | |
458 | ||
459 | /* Pull the GPIO low to select SET0 register, while we program SET1 */ | |
460 | if (gpio >= 0) | |
461 | gpio_direction_output(gpio, 0); | |
d506719f A |
462 | |
463 | step = volt_mv - TPS62361_BASE_VOLT_MV; | |
464 | step /= 10; | |
465 | ||
d506719f | 466 | debug("do_scale_tps62361: volt - %d step - 0x%x\n", volt_mv, step); |
a78274b2 | 467 | if (omap_vc_bypass_send_value(TPS62361_I2C_SLAVE_ADDR, reg, step)) |
d506719f | 468 | puts("Scaling voltage failed for vdd_mpu from TPS\n"); |
3acb5534 NM |
469 | |
470 | /* Pull the GPIO high to select SET1 register */ | |
471 | if (gpio >= 0) | |
472 | gpio_direction_output(gpio, 1); | |
d506719f A |
473 | } |
474 | ||
2e5ba489 | 475 | void do_scale_vcore(u32 vcore_reg, u32 volt_mv) |
3776801d | 476 | { |
a78274b2 | 477 | u32 offset_code; |
3776801d A |
478 | u32 offset = volt_mv; |
479 | ||
480 | /* convert to uV for better accuracy in the calculations */ | |
481 | offset *= 1000; | |
482 | ||
8de17f46 | 483 | offset_code = get_offset_code(offset); |
3776801d A |
484 | |
485 | debug("do_scale_vcore: volt - %d offset_code - 0x%x\n", volt_mv, | |
486 | offset_code); | |
8de17f46 | 487 | |
a78274b2 NM |
488 | if (omap_vc_bypass_send_value(SMPS_I2C_SLAVE_ADDR, |
489 | vcore_reg, offset_code)) | |
3776801d | 490 | printf("Scaling voltage failed for 0x%x\n", vcore_reg); |
3776801d A |
491 | } |
492 | ||
01b753ff | 493 | static inline void enable_clock_domain(u32 const clkctrl_reg, u32 enable_mode) |
3776801d A |
494 | { |
495 | clrsetbits_le32(clkctrl_reg, CD_CLKCTRL_CLKTRCTRL_MASK, | |
496 | enable_mode << CD_CLKCTRL_CLKTRCTRL_SHIFT); | |
01b753ff | 497 | debug("Enable clock domain - %x\n", clkctrl_reg); |
3776801d A |
498 | } |
499 | ||
01b753ff | 500 | static inline void wait_for_clk_enable(u32 clkctrl_addr) |
3776801d A |
501 | { |
502 | u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_DISABLED; | |
503 | u32 bound = LDELAY; | |
504 | ||
505 | while ((idlest == MODULE_CLKCTRL_IDLEST_DISABLED) || | |
506 | (idlest == MODULE_CLKCTRL_IDLEST_TRANSITIONING)) { | |
507 | ||
508 | clkctrl = readl(clkctrl_addr); | |
509 | idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >> | |
510 | MODULE_CLKCTRL_IDLEST_SHIFT; | |
511 | if (--bound == 0) { | |
01b753ff | 512 | printf("Clock enable failed for 0x%x idlest 0x%x\n", |
3776801d A |
513 | clkctrl_addr, clkctrl); |
514 | return; | |
515 | } | |
516 | } | |
517 | } | |
518 | ||
01b753ff | 519 | static inline void enable_clock_module(u32 const clkctrl_addr, u32 enable_mode, |
3776801d A |
520 | u32 wait_for_enable) |
521 | { | |
522 | clrsetbits_le32(clkctrl_addr, MODULE_CLKCTRL_MODULEMODE_MASK, | |
523 | enable_mode << MODULE_CLKCTRL_MODULEMODE_SHIFT); | |
01b753ff | 524 | debug("Enable clock module - %x\n", clkctrl_addr); |
3776801d A |
525 | if (wait_for_enable) |
526 | wait_for_clk_enable(clkctrl_addr); | |
527 | } | |
528 | ||
3776801d A |
529 | void freq_update_core(void) |
530 | { | |
531 | u32 freq_config1 = 0; | |
532 | const struct dpll_params *core_dpll_params; | |
f4010734 | 533 | u32 omap_rev = omap_revision(); |
3776801d | 534 | |
ee9447bf | 535 | core_dpll_params = get_core_dpll_params(*dplls_data); |
3776801d | 536 | /* Put EMIF clock domain in sw wakeup mode */ |
01b753ff | 537 | enable_clock_domain((*prcm)->cm_memif_clkstctrl, |
3776801d | 538 | CD_CLKCTRL_CLKTRCTRL_SW_WKUP); |
01b753ff S |
539 | wait_for_clk_enable((*prcm)->cm_memif_emif_1_clkctrl); |
540 | wait_for_clk_enable((*prcm)->cm_memif_emif_2_clkctrl); | |
3776801d A |
541 | |
542 | freq_config1 = SHADOW_FREQ_CONFIG1_FREQ_UPDATE_MASK | | |
543 | SHADOW_FREQ_CONFIG1_DLL_RESET_MASK; | |
544 | ||
545 | freq_config1 |= (DPLL_EN_LOCK << SHADOW_FREQ_CONFIG1_DPLL_EN_SHIFT) & | |
546 | SHADOW_FREQ_CONFIG1_DPLL_EN_MASK; | |
547 | ||
548 | freq_config1 |= (core_dpll_params->m2 << | |
549 | SHADOW_FREQ_CONFIG1_M2_DIV_SHIFT) & | |
550 | SHADOW_FREQ_CONFIG1_M2_DIV_MASK; | |
551 | ||
01b753ff | 552 | writel(freq_config1, (*prcm)->cm_shadow_freq_config1); |
3776801d | 553 | if (!wait_on_value(SHADOW_FREQ_CONFIG1_FREQ_UPDATE_MASK, 0, |
01b753ff | 554 | (u32 *) (*prcm)->cm_shadow_freq_config1, LDELAY)) { |
3776801d A |
555 | puts("FREQ UPDATE procedure failed!!"); |
556 | hang(); | |
557 | } | |
558 | ||
f4010734 S |
559 | /* |
560 | * Putting EMIF in HW_AUTO is seen to be causing issues with | |
561 | * EMIF clocks and the master DLL. Put EMIF in SW_WKUP | |
562 | * in OMAP5430 ES1.0 silicon | |
563 | */ | |
564 | if (omap_rev != OMAP5430_ES1_0) { | |
565 | /* Put EMIF clock domain back in hw auto mode */ | |
01b753ff | 566 | enable_clock_domain((*prcm)->cm_memif_clkstctrl, |
f4010734 | 567 | CD_CLKCTRL_CLKTRCTRL_HW_AUTO); |
01b753ff S |
568 | wait_for_clk_enable((*prcm)->cm_memif_emif_1_clkctrl); |
569 | wait_for_clk_enable((*prcm)->cm_memif_emif_2_clkctrl); | |
f4010734 | 570 | } |
3776801d A |
571 | } |
572 | ||
01b753ff | 573 | void bypass_dpll(u32 const base) |
3776801d A |
574 | { |
575 | do_bypass_dpll(base); | |
576 | wait_for_bypass(base); | |
577 | } | |
578 | ||
01b753ff | 579 | void lock_dpll(u32 const base) |
3776801d A |
580 | { |
581 | do_lock_dpll(base); | |
582 | wait_for_lock(base); | |
583 | } | |
584 | ||
bcae7211 A |
585 | void setup_clocks_for_console(void) |
586 | { | |
587 | /* Do not add any spl_debug prints in this function */ | |
01b753ff | 588 | clrsetbits_le32((*prcm)->cm_l4per_clkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK, |
bcae7211 A |
589 | CD_CLKCTRL_CLKTRCTRL_SW_WKUP << |
590 | CD_CLKCTRL_CLKTRCTRL_SHIFT); | |
591 | ||
592 | /* Enable all UARTs - console will be on one of them */ | |
01b753ff | 593 | clrsetbits_le32((*prcm)->cm_l4per_uart1_clkctrl, |
bcae7211 A |
594 | MODULE_CLKCTRL_MODULEMODE_MASK, |
595 | MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << | |
596 | MODULE_CLKCTRL_MODULEMODE_SHIFT); | |
597 | ||
01b753ff | 598 | clrsetbits_le32((*prcm)->cm_l4per_uart2_clkctrl, |
bcae7211 A |
599 | MODULE_CLKCTRL_MODULEMODE_MASK, |
600 | MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << | |
601 | MODULE_CLKCTRL_MODULEMODE_SHIFT); | |
602 | ||
01b753ff | 603 | clrsetbits_le32((*prcm)->cm_l4per_uart3_clkctrl, |
bcae7211 A |
604 | MODULE_CLKCTRL_MODULEMODE_MASK, |
605 | MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << | |
606 | MODULE_CLKCTRL_MODULEMODE_SHIFT); | |
607 | ||
01b753ff | 608 | clrsetbits_le32((*prcm)->cm_l4per_uart3_clkctrl, |
bcae7211 A |
609 | MODULE_CLKCTRL_MODULEMODE_MASK, |
610 | MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << | |
611 | MODULE_CLKCTRL_MODULEMODE_SHIFT); | |
612 | ||
01b753ff | 613 | clrsetbits_le32((*prcm)->cm_l4per_clkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK, |
bcae7211 A |
614 | CD_CLKCTRL_CLKTRCTRL_HW_AUTO << |
615 | CD_CLKCTRL_CLKTRCTRL_SHIFT); | |
616 | } | |
617 | ||
01b753ff S |
618 | void do_enable_clocks(u32 const *clk_domains, |
619 | u32 const *clk_modules_hw_auto, | |
620 | u32 const *clk_modules_explicit_en, | |
2e5ba489 S |
621 | u8 wait_for_enable) |
622 | { | |
623 | u32 i, max = 100; | |
624 | ||
625 | /* Put the clock domains in SW_WKUP mode */ | |
626 | for (i = 0; (i < max) && clk_domains[i]; i++) { | |
627 | enable_clock_domain(clk_domains[i], | |
628 | CD_CLKCTRL_CLKTRCTRL_SW_WKUP); | |
629 | } | |
630 | ||
631 | /* Clock modules that need to be put in HW_AUTO */ | |
632 | for (i = 0; (i < max) && clk_modules_hw_auto[i]; i++) { | |
633 | enable_clock_module(clk_modules_hw_auto[i], | |
634 | MODULE_CLKCTRL_MODULEMODE_HW_AUTO, | |
635 | wait_for_enable); | |
636 | }; | |
637 | ||
638 | /* Clock modules that need to be put in SW_EXPLICIT_EN mode */ | |
639 | for (i = 0; (i < max) && clk_modules_explicit_en[i]; i++) { | |
640 | enable_clock_module(clk_modules_explicit_en[i], | |
641 | MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN, | |
642 | wait_for_enable); | |
643 | }; | |
644 | ||
645 | /* Put the clock domains in HW_AUTO mode now */ | |
646 | for (i = 0; (i < max) && clk_domains[i]; i++) { | |
647 | enable_clock_domain(clk_domains[i], | |
648 | CD_CLKCTRL_CLKTRCTRL_HW_AUTO); | |
649 | } | |
650 | } | |
651 | ||
3776801d A |
652 | void prcm_init(void) |
653 | { | |
508a58fa | 654 | switch (omap_hw_init_context()) { |
3776801d A |
655 | case OMAP_INIT_CONTEXT_SPL: |
656 | case OMAP_INIT_CONTEXT_UBOOT_FROM_NOR: | |
657 | case OMAP_INIT_CONTEXT_UBOOT_AFTER_CH: | |
25223a68 | 658 | enable_basic_clocks(); |
3776801d A |
659 | scale_vcores(); |
660 | setup_dplls(); | |
78f455c0 | 661 | #ifdef CONFIG_SYS_CLOCKS_ENABLE_ALL |
3776801d A |
662 | setup_non_essential_dplls(); |
663 | enable_non_essential_clocks(); | |
78f455c0 | 664 | #endif |
3776801d A |
665 | break; |
666 | default: | |
667 | break; | |
668 | } | |
78f455c0 S |
669 | |
670 | if (OMAP_INIT_CONTEXT_SPL != omap_hw_init_context()) | |
671 | enable_basic_uboot_clocks(); | |
3776801d | 672 | } |