]>
Commit | Line | Data |
---|---|---|
b9bb0531 SB |
1 | /* |
2 | * (C) Copyright 2007 | |
3 | * Sascha Hauer, Pengutronix | |
4 | * | |
5 | * (C) Copyright 2008-2010 Freescale Semiconductor, Inc. | |
6 | * | |
1a459660 | 7 | * SPDX-License-Identifier: GPL-2.0+ |
b9bb0531 SB |
8 | */ |
9 | ||
10 | #include <common.h> | |
e7619554 | 11 | #include <div64.h> |
b9bb0531 | 12 | #include <asm/io.h> |
1221ce45 | 13 | #include <linux/errno.h> |
b9bb0531 SB |
14 | #include <asm/arch/imx-regs.h> |
15 | #include <asm/arch/crm_regs.h> | |
16 | #include <asm/arch/clock.h> | |
17 | #include <asm/arch/sys_proto.h> | |
09bc3d04 BT |
18 | #ifdef CONFIG_FSL_ESDHC |
19 | #include <fsl_esdhc.h> | |
20 | #endif | |
b9bb0531 | 21 | #include <netdev.h> |
d41924a2 | 22 | #include <spl.h> |
b9bb0531 SB |
23 | |
24 | #define CLK_CODE(arm, ahb, sel) (((arm) << 16) + ((ahb) << 8) + (sel)) | |
25 | #define CLK_CODE_ARM(c) (((c) >> 16) & 0xFF) | |
26 | #define CLK_CODE_AHB(c) (((c) >> 8) & 0xFF) | |
27 | #define CLK_CODE_PATH(c) ((c) & 0xFF) | |
28 | ||
29 | #define CCM_GET_DIVIDER(x, m, o) (((x) & (m)) >> (o)) | |
30 | ||
31 | #ifdef CONFIG_FSL_ESDHC | |
32 | DECLARE_GLOBAL_DATA_PTR; | |
33 | #endif | |
34 | ||
35 | static int g_clk_mux_auto[8] = { | |
36 | CLK_CODE(1, 3, 0), CLK_CODE(1, 2, 1), CLK_CODE(2, 1, 1), -1, | |
37 | CLK_CODE(1, 6, 0), CLK_CODE(1, 4, 1), CLK_CODE(2, 2, 1), -1, | |
38 | }; | |
39 | ||
40 | static int g_clk_mux_consumer[16] = { | |
41 | CLK_CODE(1, 4, 0), CLK_CODE(1, 3, 1), CLK_CODE(1, 3, 1), -1, | |
42 | -1, -1, CLK_CODE(4, 1, 0), CLK_CODE(1, 5, 0), | |
43 | CLK_CODE(1, 8, 1), CLK_CODE(1, 6, 1), CLK_CODE(2, 4, 0), -1, | |
44 | -1, -1, CLK_CODE(4, 2, 0), -1, | |
45 | }; | |
46 | ||
47 | static int hsp_div_table[3][16] = { | |
48 | {4, 3, 2, -1, -1, -1, 1, 5, 4, 3, 2, -1, -1, -1, 1, -1}, | |
49 | {-1, -1, -1, -1, -1, -1, -1, -1, 8, 6, 4, -1, -1, -1, 2, -1}, | |
50 | {3, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1}, | |
51 | }; | |
52 | ||
53 | u32 get_cpu_rev(void) | |
54 | { | |
55 | int reg; | |
56 | struct iim_regs *iim = | |
57 | (struct iim_regs *)IIM_BASE_ADDR; | |
58 | reg = readl(&iim->iim_srev); | |
59 | if (!reg) { | |
60 | reg = readw(ROMPATCH_REV); | |
61 | reg <<= 4; | |
62 | } else { | |
63 | reg += CHIP_REV_1_0; | |
64 | } | |
65 | ||
66 | return 0x35000 + (reg & 0xFF); | |
67 | } | |
68 | ||
69 | static u32 get_arm_div(u32 pdr0, u32 *fi, u32 *fd) | |
70 | { | |
71 | int *pclk_mux; | |
72 | if (pdr0 & MXC_CCM_PDR0_AUTO_CON) { | |
73 | pclk_mux = g_clk_mux_consumer + | |
74 | ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> | |
75 | MXC_CCM_PDR0_CON_MUX_DIV_OFFSET); | |
76 | } else { | |
77 | pclk_mux = g_clk_mux_auto + | |
78 | ((pdr0 & MXC_CCM_PDR0_AUTO_MUX_DIV_MASK) >> | |
79 | MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET); | |
80 | } | |
81 | ||
82 | if ((*pclk_mux) == -1) | |
83 | return -1; | |
84 | ||
85 | if (fi && fd) { | |
86 | if (!CLK_CODE_PATH(*pclk_mux)) { | |
87 | *fi = *fd = 1; | |
88 | return CLK_CODE_ARM(*pclk_mux); | |
89 | } | |
90 | if (pdr0 & MXC_CCM_PDR0_AUTO_CON) { | |
91 | *fi = 3; | |
92 | *fd = 4; | |
93 | } else { | |
94 | *fi = 2; | |
95 | *fd = 3; | |
96 | } | |
97 | } | |
98 | return CLK_CODE_ARM(*pclk_mux); | |
99 | } | |
100 | ||
101 | static int get_ahb_div(u32 pdr0) | |
102 | { | |
103 | int *pclk_mux; | |
104 | ||
105 | pclk_mux = g_clk_mux_consumer + | |
106 | ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> | |
107 | MXC_CCM_PDR0_CON_MUX_DIV_OFFSET); | |
108 | ||
109 | if ((*pclk_mux) == -1) | |
110 | return -1; | |
111 | ||
112 | return CLK_CODE_AHB(*pclk_mux); | |
113 | } | |
114 | ||
115 | static u32 decode_pll(u32 reg, u32 infreq) | |
116 | { | |
117 | u32 mfi = (reg >> 10) & 0xf; | |
e7619554 BT |
118 | s32 mfn = reg & 0x3ff; |
119 | u32 mfd = (reg >> 16) & 0x3ff; | |
b9bb0531 SB |
120 | u32 pd = (reg >> 26) & 0xf; |
121 | ||
122 | mfi = mfi <= 5 ? 5 : mfi; | |
e7619554 | 123 | mfn = mfn >= 512 ? mfn - 1024 : mfn; |
b9bb0531 SB |
124 | mfd += 1; |
125 | pd += 1; | |
126 | ||
e7619554 BT |
127 | return lldiv(2 * (u64)infreq * (mfi * mfd + mfn), |
128 | mfd * pd); | |
b9bb0531 SB |
129 | } |
130 | ||
131 | static u32 get_mcu_main_clk(void) | |
132 | { | |
133 | u32 arm_div = 0, fi = 0, fd = 0; | |
134 | struct ccm_regs *ccm = | |
135 | (struct ccm_regs *)IMX_CCM_BASE; | |
136 | arm_div = get_arm_div(readl(&ccm->pdr0), &fi, &fd); | |
9c6c5c06 | 137 | fi *= decode_pll(readl(&ccm->mpctl), MXC_HCLK); |
b9bb0531 SB |
138 | return fi / (arm_div * fd); |
139 | } | |
140 | ||
141 | static u32 get_ipg_clk(void) | |
142 | { | |
143 | u32 freq = get_mcu_main_clk(); | |
144 | struct ccm_regs *ccm = | |
145 | (struct ccm_regs *)IMX_CCM_BASE; | |
146 | u32 pdr0 = readl(&ccm->pdr0); | |
147 | ||
148 | return freq / (get_ahb_div(pdr0) * 2); | |
149 | } | |
150 | ||
151 | static u32 get_ipg_per_clk(void) | |
152 | { | |
153 | u32 freq = get_mcu_main_clk(); | |
154 | struct ccm_regs *ccm = | |
155 | (struct ccm_regs *)IMX_CCM_BASE; | |
156 | u32 pdr0 = readl(&ccm->pdr0); | |
157 | u32 pdr4 = readl(&ccm->pdr4); | |
158 | u32 div; | |
159 | if (pdr0 & MXC_CCM_PDR0_PER_SEL) { | |
82e1b543 | 160 | div = CCM_GET_DIVIDER(pdr4, |
b9bb0531 | 161 | MXC_CCM_PDR4_PER0_PODF_MASK, |
82e1b543 | 162 | MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1; |
b9bb0531 SB |
163 | } else { |
164 | div = CCM_GET_DIVIDER(pdr0, | |
165 | MXC_CCM_PDR0_PER_PODF_MASK, | |
166 | MXC_CCM_PDR0_PER_PODF_OFFSET) + 1; | |
82e1b543 | 167 | div *= get_ahb_div(pdr0); |
b9bb0531 SB |
168 | } |
169 | return freq / div; | |
170 | } | |
171 | ||
172 | u32 imx_get_uartclk(void) | |
173 | { | |
174 | u32 freq; | |
175 | struct ccm_regs *ccm = | |
176 | (struct ccm_regs *)IMX_CCM_BASE; | |
177 | u32 pdr4 = readl(&ccm->pdr4); | |
178 | ||
9c6c5c06 | 179 | if (readl(&ccm->pdr3) & MXC_CCM_PDR3_UART_M_U) |
b9bb0531 | 180 | freq = get_mcu_main_clk(); |
9c6c5c06 BT |
181 | else |
182 | freq = decode_pll(readl(&ccm->ppctl), MXC_HCLK); | |
82e1b543 | 183 | freq /= CCM_GET_DIVIDER(pdr4, |
b9bb0531 | 184 | MXC_CCM_PDR4_UART_PODF_MASK, |
82e1b543 | 185 | MXC_CCM_PDR4_UART_PODF_OFFSET) + 1; |
b9bb0531 SB |
186 | return freq; |
187 | } | |
188 | ||
7c80326d | 189 | unsigned int mxc_get_main_clock(enum mxc_main_clock clk) |
b9bb0531 SB |
190 | { |
191 | u32 nfc_pdf, hsp_podf; | |
82e1b543 | 192 | u32 pll, ret_val = 0, usb_podf; |
b9bb0531 SB |
193 | struct ccm_regs *ccm = |
194 | (struct ccm_regs *)IMX_CCM_BASE; | |
195 | ||
196 | u32 reg = readl(&ccm->pdr0); | |
197 | u32 reg4 = readl(&ccm->pdr4); | |
198 | ||
199 | reg |= 0x1; | |
200 | ||
201 | switch (clk) { | |
202 | case CPU_CLK: | |
203 | ret_val = get_mcu_main_clk(); | |
204 | break; | |
205 | case AHB_CLK: | |
206 | ret_val = get_mcu_main_clk(); | |
207 | break; | |
208 | case HSP_CLK: | |
209 | if (reg & CLKMODE_CONSUMER) { | |
210 | hsp_podf = (reg >> 20) & 0x3; | |
211 | pll = get_mcu_main_clk(); | |
212 | hsp_podf = hsp_div_table[hsp_podf][(reg>>16)&0xF]; | |
213 | if (hsp_podf > 0) { | |
214 | ret_val = pll / hsp_podf; | |
215 | } else { | |
216 | puts("mismatch HSP with ARM clock setting\n"); | |
217 | ret_val = 0; | |
218 | } | |
219 | } else { | |
220 | ret_val = get_mcu_main_clk(); | |
221 | } | |
222 | break; | |
223 | case IPG_CLK: | |
77f11a99 | 224 | ret_val = get_ipg_clk(); |
b9bb0531 SB |
225 | break; |
226 | case IPG_PER_CLK: | |
227 | ret_val = get_ipg_per_clk(); | |
228 | break; | |
229 | case NFC_CLK: | |
230 | nfc_pdf = (reg4 >> 28) & 0xF; | |
231 | pll = get_mcu_main_clk(); | |
232 | /* AHB/nfc_pdf */ | |
233 | ret_val = pll / (nfc_pdf + 1); | |
234 | break; | |
235 | case USB_CLK: | |
82e1b543 | 236 | usb_podf = (reg4 >> 22) & 0x3F; |
9c6c5c06 | 237 | if (reg4 & 0x200) |
b9bb0531 | 238 | pll = get_mcu_main_clk(); |
9c6c5c06 BT |
239 | else |
240 | pll = decode_pll(readl(&ccm->ppctl), MXC_HCLK); | |
b9bb0531 | 241 | |
82e1b543 | 242 | ret_val = pll / (usb_podf + 1); |
b9bb0531 SB |
243 | break; |
244 | default: | |
245 | printf("Unknown clock: %d\n", clk); | |
246 | break; | |
247 | } | |
248 | ||
249 | return ret_val; | |
250 | } | |
7c80326d | 251 | unsigned int mxc_get_peri_clock(enum mxc_peri_clock clk) |
b9bb0531 SB |
252 | { |
253 | u32 ret_val = 0, pdf, pre_pdf, clk_sel; | |
254 | struct ccm_regs *ccm = | |
255 | (struct ccm_regs *)IMX_CCM_BASE; | |
256 | u32 mpdr2 = readl(&ccm->pdr2); | |
257 | u32 mpdr3 = readl(&ccm->pdr3); | |
258 | u32 mpdr4 = readl(&ccm->pdr4); | |
259 | ||
260 | switch (clk) { | |
261 | case UART1_BAUD: | |
262 | case UART2_BAUD: | |
263 | case UART3_BAUD: | |
264 | clk_sel = mpdr3 & (1 << 14); | |
82e1b543 | 265 | pdf = (mpdr4 >> 10) & 0x3F; |
b9bb0531 | 266 | ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : |
9c6c5c06 | 267 | decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); |
b9bb0531 SB |
268 | break; |
269 | case SSI1_BAUD: | |
270 | pre_pdf = (mpdr2 >> 24) & 0x7; | |
271 | pdf = mpdr2 & 0x3F; | |
272 | clk_sel = mpdr2 & (1 << 6); | |
273 | ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : | |
9c6c5c06 | 274 | decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / |
b9bb0531 SB |
275 | ((pre_pdf + 1) * (pdf + 1)); |
276 | break; | |
277 | case SSI2_BAUD: | |
278 | pre_pdf = (mpdr2 >> 27) & 0x7; | |
279 | pdf = (mpdr2 >> 8) & 0x3F; | |
280 | clk_sel = mpdr2 & (1 << 6); | |
281 | ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : | |
9c6c5c06 | 282 | decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / |
b9bb0531 SB |
283 | ((pre_pdf + 1) * (pdf + 1)); |
284 | break; | |
285 | case CSI_BAUD: | |
286 | clk_sel = mpdr2 & (1 << 7); | |
82e1b543 | 287 | pdf = (mpdr2 >> 16) & 0x3F; |
b9bb0531 | 288 | ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : |
9c6c5c06 | 289 | decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); |
b9bb0531 SB |
290 | break; |
291 | case MSHC_CLK: | |
292 | pre_pdf = readl(&ccm->pdr1); | |
293 | clk_sel = (pre_pdf & 0x80); | |
294 | pdf = (pre_pdf >> 22) & 0x3F; | |
295 | pre_pdf = (pre_pdf >> 28) & 0x7; | |
296 | ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : | |
9c6c5c06 | 297 | decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / |
b9bb0531 SB |
298 | ((pre_pdf + 1) * (pdf + 1)); |
299 | break; | |
300 | case ESDHC1_CLK: | |
301 | clk_sel = mpdr3 & 0x40; | |
82e1b543 | 302 | pdf = mpdr3 & 0x3F; |
b9bb0531 | 303 | ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : |
9c6c5c06 | 304 | decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); |
b9bb0531 SB |
305 | break; |
306 | case ESDHC2_CLK: | |
307 | clk_sel = mpdr3 & 0x40; | |
82e1b543 | 308 | pdf = (mpdr3 >> 8) & 0x3F; |
b9bb0531 | 309 | ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : |
9c6c5c06 | 310 | decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); |
b9bb0531 SB |
311 | break; |
312 | case ESDHC3_CLK: | |
313 | clk_sel = mpdr3 & 0x40; | |
82e1b543 | 314 | pdf = (mpdr3 >> 16) & 0x3F; |
b9bb0531 | 315 | ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : |
9c6c5c06 | 316 | decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); |
b9bb0531 SB |
317 | break; |
318 | case SPDIF_CLK: | |
319 | clk_sel = mpdr3 & 0x400000; | |
320 | pre_pdf = (mpdr3 >> 29) & 0x7; | |
321 | pdf = (mpdr3 >> 23) & 0x3F; | |
322 | ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : | |
9c6c5c06 | 323 | decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / |
b9bb0531 SB |
324 | ((pre_pdf + 1) * (pdf + 1)); |
325 | break; | |
326 | default: | |
327 | printf("%s(): This clock: %d not supported yet\n", | |
328 | __func__, clk); | |
329 | break; | |
330 | } | |
331 | ||
332 | return ret_val; | |
333 | } | |
334 | ||
335 | unsigned int mxc_get_clock(enum mxc_clock clk) | |
336 | { | |
337 | switch (clk) { | |
338 | case MXC_ARM_CLK: | |
339 | return get_mcu_main_clk(); | |
340 | case MXC_AHB_CLK: | |
341 | break; | |
342 | case MXC_IPG_CLK: | |
343 | return get_ipg_clk(); | |
344 | case MXC_IPG_PERCLK: | |
e7bed5c2 | 345 | case MXC_I2C_CLK: |
b9bb0531 SB |
346 | return get_ipg_per_clk(); |
347 | case MXC_UART_CLK: | |
348 | return imx_get_uartclk(); | |
6e3dc127 | 349 | case MXC_ESDHC1_CLK: |
b9bb0531 | 350 | return mxc_get_peri_clock(ESDHC1_CLK); |
6e3dc127 BT |
351 | case MXC_ESDHC2_CLK: |
352 | return mxc_get_peri_clock(ESDHC2_CLK); | |
353 | case MXC_ESDHC3_CLK: | |
354 | return mxc_get_peri_clock(ESDHC3_CLK); | |
b9bb0531 SB |
355 | case MXC_USB_CLK: |
356 | return mxc_get_main_clock(USB_CLK); | |
357 | case MXC_FEC_CLK: | |
358 | return get_ipg_clk(); | |
359 | case MXC_CSPI_CLK: | |
360 | return get_ipg_clk(); | |
361 | } | |
362 | return -1; | |
363 | } | |
364 | ||
365 | #ifdef CONFIG_FEC_MXC | |
366 | /* | |
367 | * The MX35 has no fuse for MAC, return a NULL MAC | |
368 | */ | |
be252b65 | 369 | void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) |
b9bb0531 SB |
370 | { |
371 | memset(mac, 0, 6); | |
372 | } | |
373 | ||
374 | u32 imx_get_fecclk(void) | |
375 | { | |
376 | return mxc_get_clock(MXC_IPG_CLK); | |
377 | } | |
378 | #endif | |
379 | ||
380 | int do_mx35_showclocks(cmd_tbl_t *cmdtp, | |
381 | int flag, int argc, char * const argv[]) | |
382 | { | |
383 | u32 cpufreq = get_mcu_main_clk(); | |
384 | printf("mx35 cpu clock: %dMHz\n", cpufreq / 1000000); | |
385 | printf("ipg clock : %dHz\n", get_ipg_clk()); | |
386 | printf("ipg per clock : %dHz\n", get_ipg_per_clk()); | |
387 | printf("uart clock : %dHz\n", mxc_get_clock(MXC_UART_CLK)); | |
388 | ||
389 | return 0; | |
390 | } | |
391 | ||
392 | U_BOOT_CMD( | |
7acec259 SB |
393 | clocks, CONFIG_SYS_MAXARGS, 1, do_mx35_showclocks, |
394 | "display clocks", | |
b9bb0531 SB |
395 | "" |
396 | ); | |
397 | ||
ec0919f5 | 398 | #if defined(CONFIG_DISPLAY_CPUINFO) |
d330883f SB |
399 | static char *get_reset_cause(void) |
400 | { | |
401 | /* read RCSR register from CCM module */ | |
402 | struct ccm_regs *ccm = | |
403 | (struct ccm_regs *)IMX_CCM_BASE; | |
404 | ||
405 | u32 cause = readl(&ccm->rcsr) & 0x0F; | |
406 | ||
407 | switch (cause) { | |
408 | case 0x0000: | |
409 | return "POR"; | |
410 | case 0x0002: | |
411 | return "JTAG"; | |
412 | case 0x0004: | |
413 | return "RST"; | |
414 | case 0x0008: | |
415 | return "WDOG"; | |
416 | default: | |
417 | return "unknown reset"; | |
418 | } | |
419 | } | |
420 | ||
b9bb0531 SB |
421 | int print_cpuinfo(void) |
422 | { | |
d330883f SB |
423 | u32 srev = get_cpu_rev(); |
424 | ||
425 | printf("CPU: Freescale i.MX35 rev %d.%d at %d MHz.\n", | |
426 | (srev & 0xF0) >> 4, (srev & 0x0F), | |
b9bb0531 | 427 | get_mcu_main_clk() / 1000000); |
d330883f SB |
428 | |
429 | printf("Reset cause: %s\n", get_reset_cause()); | |
430 | ||
b9bb0531 SB |
431 | return 0; |
432 | } | |
433 | #endif | |
434 | ||
435 | /* | |
436 | * Initializes on-chip ethernet controllers. | |
437 | * to override, implement board_eth_init() | |
438 | */ | |
b9bb0531 SB |
439 | int cpu_eth_init(bd_t *bis) |
440 | { | |
441 | int rc = -ENODEV; | |
442 | ||
443 | #if defined(CONFIG_FEC_MXC) | |
444 | rc = fecmxc_initialize(bis); | |
445 | #endif | |
446 | ||
447 | return rc; | |
448 | } | |
449 | ||
09bc3d04 BT |
450 | #ifdef CONFIG_FSL_ESDHC |
451 | /* | |
452 | * Initializes on-chip MMC controllers. | |
453 | * to override, implement board_mmc_init() | |
454 | */ | |
455 | int cpu_mmc_init(bd_t *bis) | |
456 | { | |
457 | return fsl_esdhc_mmc_init(bis); | |
458 | } | |
459 | #endif | |
460 | ||
b9bb0531 SB |
461 | int get_clocks(void) |
462 | { | |
463 | #ifdef CONFIG_FSL_ESDHC | |
6e3dc127 | 464 | #if CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC2_BASE_ADDR |
e9adeca3 | 465 | gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); |
6e3dc127 | 466 | #elif CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC3_BASE_ADDR |
e9adeca3 | 467 | gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); |
6e3dc127 | 468 | #else |
e9adeca3 | 469 | gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC1_CLK); |
6e3dc127 | 470 | #endif |
b9bb0531 SB |
471 | #endif |
472 | return 0; | |
473 | } | |
474 | ||
d41924a2 SB |
475 | #define RCSR_MEM_CTL_WEIM 0 |
476 | #define RCSR_MEM_CTL_NAND 1 | |
477 | #define RCSR_MEM_CTL_ATA 2 | |
478 | #define RCSR_MEM_CTL_EXPANSION 3 | |
479 | #define RCSR_MEM_TYPE_NOR 0 | |
480 | #define RCSR_MEM_TYPE_ONENAND 2 | |
481 | #define RCSR_MEM_TYPE_SD 0 | |
482 | #define RCSR_MEM_TYPE_I2C 2 | |
483 | #define RCSR_MEM_TYPE_SPI 3 | |
484 | ||
485 | u32 spl_boot_device(void) | |
486 | { | |
487 | struct ccm_regs *ccm = | |
488 | (struct ccm_regs *)IMX_CCM_BASE; | |
489 | ||
490 | u32 rcsr = readl(&ccm->rcsr); | |
491 | u32 mem_type, mem_ctl; | |
492 | ||
493 | /* In external mode, no boot device is returned */ | |
494 | if ((rcsr >> 10) & 0x03) | |
495 | return BOOT_DEVICE_NONE; | |
496 | ||
497 | mem_ctl = (rcsr >> 25) & 0x03; | |
498 | mem_type = (rcsr >> 23) & 0x03; | |
499 | ||
500 | switch (mem_ctl) { | |
501 | case RCSR_MEM_CTL_WEIM: | |
502 | switch (mem_type) { | |
503 | case RCSR_MEM_TYPE_NOR: | |
504 | return BOOT_DEVICE_NOR; | |
505 | case RCSR_MEM_TYPE_ONENAND: | |
66c7f399 | 506 | return BOOT_DEVICE_ONENAND; |
d41924a2 SB |
507 | default: |
508 | return BOOT_DEVICE_NONE; | |
509 | } | |
510 | case RCSR_MEM_CTL_NAND: | |
511 | return BOOT_DEVICE_NAND; | |
512 | case RCSR_MEM_CTL_EXPANSION: | |
513 | switch (mem_type) { | |
514 | case RCSR_MEM_TYPE_SD: | |
515 | return BOOT_DEVICE_MMC1; | |
516 | case RCSR_MEM_TYPE_I2C: | |
517 | return BOOT_DEVICE_I2C; | |
518 | case RCSR_MEM_TYPE_SPI: | |
519 | return BOOT_DEVICE_SPI; | |
520 | default: | |
521 | return BOOT_DEVICE_NONE; | |
522 | } | |
523 | } | |
524 | ||
525 | return BOOT_DEVICE_NONE; | |
526 | } |