]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
42d1f039 | 2 | /* |
beba93ed | 3 | * Copyright 2004,2007-2011 Freescale Semiconductor, Inc. |
42d1f039 WD |
4 | * (C) Copyright 2002, 2003 Motorola Inc. |
5 | * Xianghua Xiao (X.Xiao@motorola.com) | |
6 | * | |
7 | * (C) Copyright 2000 | |
8 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
42d1f039 WD |
9 | */ |
10 | ||
75b9d4ae | 11 | #include <config.h> |
42d1f039 | 12 | #include <common.h> |
62f9b654 | 13 | #include <cpu_func.h> |
691d719d | 14 | #include <init.h> |
36bf446b | 15 | #include <irq_func.h> |
049f8d6f | 16 | #include <time.h> |
2189d5f1 | 17 | #include <vsprintf.h> |
42d1f039 WD |
18 | #include <watchdog.h> |
19 | #include <command.h> | |
80522dc8 | 20 | #include <fsl_esdhc.h> |
42d1f039 | 21 | #include <asm/cache.h> |
740280e6 | 22 | #include <asm/io.h> |
199e262e | 23 | #include <asm/mmu.h> |
0b66513b | 24 | #include <fsl_ifc.h> |
199e262e | 25 | #include <asm/fsl_law.h> |
38dba0c2 | 26 | #include <asm/fsl_lbc.h> |
ebbe11dd YS |
27 | #include <post.h> |
28 | #include <asm/processor.h> | |
5614e71b | 29 | #include <fsl_ddr_sdram.h> |
f3603b43 | 30 | #include <asm/ppc.h> |
42d1f039 | 31 | |
591933ca JY |
32 | DECLARE_GLOBAL_DATA_PTR; |
33 | ||
c18de0d7 IS |
34 | /* |
35 | * Default board reset function | |
36 | */ | |
37 | static void | |
38 | __board_reset(void) | |
39 | { | |
40 | /* Do nothing */ | |
41 | } | |
42 | void board_reset(void) __attribute__((weak, alias("__board_reset"))); | |
43 | ||
42d1f039 WD |
44 | int checkcpu (void) |
45 | { | |
97d80fc3 | 46 | sys_info_t sysinfo; |
97d80fc3 WD |
47 | uint pvr, svr; |
48 | uint ver; | |
49 | uint major, minor; | |
4dbdb768 | 50 | struct cpu_type *cpu; |
08ef89ec | 51 | char buf1[32], buf2[32]; |
f165bc35 YS |
52 | #if defined(CONFIG_DDR_CLK_FREQ) || defined(CONFIG_FSL_CORENET) |
53 | ccsr_gur_t __iomem *gur = | |
54 | (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); | |
55 | #endif | |
98ffa190 YS |
56 | |
57 | /* | |
58 | * Cornet platforms use ddr sync bit in RCW to indicate sync vs async | |
59 | * mode. Previous platform use ddr ratio to do the same. This | |
60 | * information is only for display here. | |
61 | */ | |
39aaca1f | 62 | #ifdef CONFIG_FSL_CORENET |
379c5145 | 63 | #ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2 |
98ffa190 | 64 | u32 ddr_sync = 0; /* only async mode is supported */ |
379c5145 | 65 | #else |
98ffa190 | 66 | u32 ddr_sync = ((gur->rcwsr[5]) & FSL_CORENET_RCWSR5_DDR_SYNC) |
ab48ca1a | 67 | >> FSL_CORENET_RCWSR5_DDR_SYNC_SHIFT; |
379c5145 | 68 | #endif /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */ |
98ffa190 YS |
69 | #else /* CONFIG_FSL_CORENET */ |
70 | #ifdef CONFIG_DDR_CLK_FREQ | |
71 | u32 ddr_ratio = ((gur->porpllsr) & MPC85xx_PORPLLSR_DDR_RATIO) | |
72 | >> MPC85xx_PORPLLSR_DDR_RATIO_SHIFT; | |
ee1e35be KG |
73 | #else |
74 | u32 ddr_ratio = 0; | |
39aaca1f | 75 | #endif /* CONFIG_DDR_CLK_FREQ */ |
98ffa190 YS |
76 | #endif /* CONFIG_FSL_CORENET */ |
77 | ||
fbb9ecf7 TT |
78 | unsigned int i, core, nr_cores = cpu_numcores(); |
79 | u32 mask = cpu_mask(); | |
97d80fc3 | 80 | |
b8bf0adc SL |
81 | #ifdef CONFIG_HETROGENOUS_CLUSTERS |
82 | unsigned int j, dsp_core, dsp_numcores = cpu_num_dspcores(); | |
83 | u32 dsp_mask = cpu_dsp_mask(); | |
84 | #endif | |
85 | ||
97d80fc3 | 86 | svr = get_svr(); |
97d80fc3 WD |
87 | major = SVR_MAJ(svr); |
88 | minor = SVR_MIN(svr); | |
42d1f039 | 89 | |
5122dfae SL |
90 | #if defined(CONFIG_SYS_FSL_QORIQ_CHASSIS2) && defined(CONFIG_E6500) |
91 | if (SVR_SOC_VER(svr) == SVR_T4080) { | |
92 | ccsr_rcpm_t *rcpm = | |
93 | (void __iomem *)(CONFIG_SYS_FSL_CORENET_RCPM_ADDR); | |
94 | ||
95 | setbits_be32(&gur->devdisr2, FSL_CORENET_DEVDISR2_DTSEC1_6 || | |
96 | FSL_CORENET_DEVDISR2_DTSEC1_9); | |
97 | setbits_be32(&gur->devdisr3, FSL_CORENET_DEVDISR3_PCIE3); | |
98 | setbits_be32(&gur->devdisr5, FSL_CORENET_DEVDISR5_DDR3); | |
99 | ||
100 | /* It needs SW to disable core4~7 as HW design sake on T4080 */ | |
101 | for (i = 4; i < 8; i++) | |
102 | cpu_disable(i); | |
103 | ||
104 | /* request core4~7 into PH20 state, prior to entering PCL10 | |
105 | * state, all cores in cluster should be placed in PH20 state. | |
106 | */ | |
107 | setbits_be32(&rcpm->pcph20setr, 0xf0); | |
108 | ||
109 | /* put the 2nd cluster into PCL10 state */ | |
110 | setbits_be32(&rcpm->clpcl10setr, 1 << 1); | |
111 | } | |
112 | #endif | |
113 | ||
0e870980 | 114 | if (cpu_numcores() > 1) { |
21170c80 PA |
115 | #ifndef CONFIG_MP |
116 | puts("Unicore software on multiprocessor system!!\n" | |
117 | "To enable mutlticore build define CONFIG_MP\n"); | |
118 | #endif | |
680c613a | 119 | volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC8xxx_PIC_ADDR); |
0e870980 PA |
120 | printf("CPU%d: ", pic->whoami); |
121 | } else { | |
122 | puts("CPU: "); | |
123 | } | |
1ced1216 | 124 | |
67ac13b1 | 125 | cpu = gd->arch.cpu; |
1ced1216 | 126 | |
58442dc0 PA |
127 | puts(cpu->name); |
128 | if (IS_E_PROCESSOR(svr)) | |
129 | puts("E"); | |
1ced1216 | 130 | |
97d80fc3 WD |
131 | printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr); |
132 | ||
6c9e789e WD |
133 | pvr = get_pvr(); |
134 | ver = PVR_VER(pvr); | |
135 | major = PVR_MAJ(pvr); | |
136 | minor = PVR_MIN(pvr); | |
137 | ||
138 | printf("Core: "); | |
8992738d KG |
139 | switch(ver) { |
140 | case PVR_VER_E500_V1: | |
141 | case PVR_VER_E500_V2: | |
6770c5e2 | 142 | puts("e500"); |
8992738d KG |
143 | break; |
144 | case PVR_VER_E500MC: | |
6770c5e2 | 145 | puts("e500mc"); |
8992738d KG |
146 | break; |
147 | case PVR_VER_E5500: | |
6770c5e2 | 148 | puts("e5500"); |
8992738d | 149 | break; |
5b6b85ae | 150 | case PVR_VER_E6500: |
6770c5e2 | 151 | puts("e6500"); |
5b6b85ae | 152 | break; |
8992738d | 153 | default: |
2a3a96ca | 154 | puts("Unknown"); |
8992738d | 155 | break; |
6c9e789e | 156 | } |
0f060c3b | 157 | |
6c9e789e WD |
158 | printf(", Version: %d.%d, (0x%08x)\n", major, minor, pvr); |
159 | ||
2f1712b2 YS |
160 | if (nr_cores > CONFIG_MAX_CPUS) { |
161 | panic("\nUnexpected number of cores: %d, max is %d\n", | |
162 | nr_cores, CONFIG_MAX_CPUS); | |
163 | } | |
164 | ||
97d80fc3 WD |
165 | get_sys_info(&sysinfo); |
166 | ||
0c12a159 | 167 | #ifdef CONFIG_SYS_FSL_SINGLE_SOURCE_CLK |
168 | if (sysinfo.diff_sysclk == 1) | |
169 | puts("Single Source Clock Configuration\n"); | |
170 | #endif | |
171 | ||
b29dee3c | 172 | puts("Clock Configuration:"); |
fbb9ecf7 | 173 | for_each_cpu(i, core, nr_cores, mask) { |
1bba30ef WD |
174 | if (!(i & 3)) |
175 | printf ("\n "); | |
fbb9ecf7 | 176 | printf("CPU%d:%-4s MHz, ", core, |
997399fa | 177 | strmhz(buf1, sysinfo.freq_processor[core])); |
b29dee3c | 178 | } |
b8bf0adc SL |
179 | |
180 | #ifdef CONFIG_HETROGENOUS_CLUSTERS | |
181 | for_each_cpu(j, dsp_core, dsp_numcores, dsp_mask) { | |
182 | if (!(j & 3)) | |
183 | printf("\n "); | |
184 | printf("DSP CPU%d:%-4s MHz, ", j, | |
185 | strmhz(buf1, sysinfo.freq_processor_dsp[dsp_core])); | |
186 | } | |
187 | #endif | |
188 | ||
997399fa PK |
189 | printf("\n CCB:%-4s MHz,", strmhz(buf1, sysinfo.freq_systembus)); |
190 | printf("\n"); | |
ee1e35be | 191 | |
39aaca1f KG |
192 | #ifdef CONFIG_FSL_CORENET |
193 | if (ddr_sync == 1) { | |
194 | printf(" DDR:%-4s MHz (%s MT/s data rate) " | |
195 | "(Synchronous), ", | |
997399fa PK |
196 | strmhz(buf1, sysinfo.freq_ddrbus/2), |
197 | strmhz(buf2, sysinfo.freq_ddrbus)); | |
39aaca1f KG |
198 | } else { |
199 | printf(" DDR:%-4s MHz (%s MT/s data rate) " | |
200 | "(Asynchronous), ", | |
997399fa PK |
201 | strmhz(buf1, sysinfo.freq_ddrbus/2), |
202 | strmhz(buf2, sysinfo.freq_ddrbus)); | |
39aaca1f KG |
203 | } |
204 | #else | |
d4357932 KG |
205 | switch (ddr_ratio) { |
206 | case 0x0: | |
08ef89ec | 207 | printf(" DDR:%-4s MHz (%s MT/s data rate), ", |
997399fa PK |
208 | strmhz(buf1, sysinfo.freq_ddrbus/2), |
209 | strmhz(buf2, sysinfo.freq_ddrbus)); | |
d4357932 KG |
210 | break; |
211 | case 0x7: | |
39aaca1f KG |
212 | printf(" DDR:%-4s MHz (%s MT/s data rate) " |
213 | "(Synchronous), ", | |
997399fa PK |
214 | strmhz(buf1, sysinfo.freq_ddrbus/2), |
215 | strmhz(buf2, sysinfo.freq_ddrbus)); | |
d4357932 KG |
216 | break; |
217 | default: | |
39aaca1f KG |
218 | printf(" DDR:%-4s MHz (%s MT/s data rate) " |
219 | "(Asynchronous), ", | |
997399fa PK |
220 | strmhz(buf1, sysinfo.freq_ddrbus/2), |
221 | strmhz(buf2, sysinfo.freq_ddrbus)); | |
d4357932 KG |
222 | break; |
223 | } | |
39aaca1f | 224 | #endif |
97d80fc3 | 225 | |
beba93ed | 226 | #if defined(CONFIG_FSL_LBC) |
997399fa PK |
227 | if (sysinfo.freq_localbus > LCRR_CLKDIV) { |
228 | printf("LBC:%-4s MHz\n", strmhz(buf1, sysinfo.freq_localbus)); | |
39aaca1f | 229 | } else { |
ada591d2 | 230 | printf("LBC: unknown (LCRR[CLKDIV] = 0x%02lx)\n", |
997399fa | 231 | sysinfo.freq_localbus); |
39aaca1f | 232 | } |
beba93ed | 233 | #endif |
42d1f039 | 234 | |
800c73c4 | 235 | #if defined(CONFIG_FSL_IFC) |
997399fa | 236 | printf("IFC:%-4s MHz\n", strmhz(buf1, sysinfo.freq_localbus)); |
800c73c4 KG |
237 | #endif |
238 | ||
1ced1216 | 239 | #ifdef CONFIG_CPM2 |
997399fa | 240 | printf("CPM: %s MHz\n", strmhz(buf1, sysinfo.freq_systembus)); |
1ced1216 | 241 | #endif |
97d80fc3 | 242 | |
b3d7f20f | 243 | #ifdef CONFIG_QE |
997399fa | 244 | printf(" QE:%-4s MHz\n", strmhz(buf1, sysinfo.freq_qe)); |
b3d7f20f HW |
245 | #endif |
246 | ||
b8bf0adc SL |
247 | #if defined(CONFIG_SYS_CPRI) |
248 | printf(" "); | |
249 | printf("CPRI:%-4s MHz", strmhz(buf1, sysinfo.freq_cpri)); | |
250 | #endif | |
251 | ||
252 | #if defined(CONFIG_SYS_MAPLE) | |
253 | printf("\n "); | |
254 | printf("MAPLE:%-4s MHz, ", strmhz(buf1, sysinfo.freq_maple)); | |
255 | printf("MAPLE-ULB:%-4s MHz, ", strmhz(buf1, sysinfo.freq_maple_ulb)); | |
256 | printf("MAPLE-eTVPE:%-4s MHz\n", | |
257 | strmhz(buf1, sysinfo.freq_maple_etvpe)); | |
258 | #endif | |
259 | ||
39aaca1f KG |
260 | #ifdef CONFIG_SYS_DPAA_FMAN |
261 | for (i = 0; i < CONFIG_SYS_NUM_FMAN; i++) { | |
7eda1f8e | 262 | printf(" FMAN%d: %s MHz\n", i + 1, |
997399fa | 263 | strmhz(buf1, sysinfo.freq_fman[i])); |
39aaca1f KG |
264 | } |
265 | #endif | |
266 | ||
990e1a8c | 267 | #ifdef CONFIG_SYS_DPAA_QBMAN |
997399fa | 268 | printf(" QMAN: %s MHz\n", strmhz(buf1, sysinfo.freq_qman)); |
990e1a8c HW |
269 | #endif |
270 | ||
39aaca1f | 271 | #ifdef CONFIG_SYS_DPAA_PME |
997399fa | 272 | printf(" PME: %s MHz\n", strmhz(buf1, sysinfo.freq_pme)); |
39aaca1f KG |
273 | #endif |
274 | ||
6b44d9e5 | 275 | puts("L1: D-cache 32 KiB enabled\n I-cache 32 KiB enabled\n"); |
42d1f039 | 276 | |
f165bc35 YS |
277 | #ifdef CONFIG_FSL_CORENET |
278 | /* Display the RCW, so that no one gets confused as to what RCW | |
279 | * we're actually using for this boot. | |
280 | */ | |
281 | puts("Reset Configuration Word (RCW):"); | |
282 | for (i = 0; i < ARRAY_SIZE(gur->rcwsr); i++) { | |
283 | u32 rcw = in_be32(&gur->rcwsr[i]); | |
284 | ||
285 | if ((i % 4) == 0) | |
286 | printf("\n %08x:", i * 4); | |
287 | printf(" %08x", rcw); | |
288 | } | |
289 | puts("\n"); | |
290 | #endif | |
291 | ||
42d1f039 WD |
292 | return 0; |
293 | } | |
294 | ||
295 | ||
296 | /* ------------------------------------------------------------------------- */ | |
297 | ||
09140113 | 298 | int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) |
42d1f039 | 299 | { |
c348322a | 300 | /* Everything after the first generation of PQ3 parts has RSTCR */ |
3aff3082 | 301 | #if defined(CONFIG_ARCH_MPC8540) || defined(CONFIG_ARCH_MPC8541) || \ |
99d0a312 | 302 | defined(CONFIG_ARCH_MPC8555) || defined(CONFIG_ARCH_MPC8560) |
793670c3 SP |
303 | unsigned long val, msr; |
304 | ||
42d1f039 WD |
305 | /* |
306 | * Initiate hard reset in debug control register DBCR0 | |
c348322a | 307 | * Make sure MSR[DE] = 1. This only resets the core. |
42d1f039 | 308 | */ |
793670c3 SP |
309 | msr = mfmsr (); |
310 | msr |= MSR_DE; | |
311 | mtmsr (msr); | |
312 | ||
313 | val = mfspr(DBCR0); | |
314 | val |= 0x70000000; | |
315 | mtspr(DBCR0,val); | |
c348322a KG |
316 | #else |
317 | volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); | |
c18de0d7 IS |
318 | |
319 | /* Attempt board-specific reset */ | |
320 | board_reset(); | |
321 | ||
322 | /* Next try asserting HRESET_REQ */ | |
323 | out_be32(&gur->rstcr, 0x2); | |
c348322a KG |
324 | udelay(100); |
325 | #endif | |
df90968b | 326 | |
42d1f039 WD |
327 | return 1; |
328 | } | |
329 | ||
330 | ||
331 | /* | |
332 | * Get timebase clock frequency | |
333 | */ | |
66412c63 KG |
334 | #ifndef CONFIG_SYS_FSL_TBCLK_DIV |
335 | #define CONFIG_SYS_FSL_TBCLK_DIV 8 | |
336 | #endif | |
049f8d6f | 337 | __weak unsigned long get_tbclk(void) |
42d1f039 | 338 | { |
66412c63 KG |
339 | unsigned long tbclk_div = CONFIG_SYS_FSL_TBCLK_DIV; |
340 | ||
341 | return (gd->bus_clk + (tbclk_div >> 1)) / tbclk_div; | |
42d1f039 WD |
342 | } |
343 | ||
344 | ||
345 | #if defined(CONFIG_WATCHDOG) | |
0f8062b2 BR |
346 | #define WATCHDOG_MASK (TCR_WP(63) | TCR_WRC(3) | TCR_WIE) |
347 | void | |
348 | init_85xx_watchdog(void) | |
349 | { | |
350 | mtspr(SPRN_TCR, (mfspr(SPRN_TCR) & ~WATCHDOG_MASK) | | |
351 | TCR_WP(CONFIG_WATCHDOG_PRESC) | TCR_WRC(CONFIG_WATCHDOG_RC)); | |
352 | } | |
353 | ||
42d1f039 WD |
354 | void |
355 | reset_85xx_watchdog(void) | |
356 | { | |
357 | /* | |
358 | * Clear TSR(WIS) bit by writing 1 | |
359 | */ | |
320d53da | 360 | mtspr(SPRN_TSR, TSR_WIS); |
42d1f039 | 361 | } |
df616cae HK |
362 | |
363 | void | |
364 | watchdog_reset(void) | |
365 | { | |
366 | int re_enable = disable_interrupts(); | |
367 | ||
368 | reset_85xx_watchdog(); | |
369 | if (re_enable) | |
370 | enable_interrupts(); | |
371 | } | |
42d1f039 WD |
372 | #endif /* CONFIG_WATCHDOG */ |
373 | ||
80522dc8 AF |
374 | /* |
375 | * Initializes on-chip MMC controllers. | |
376 | * to override, implement board_mmc_init() | |
377 | */ | |
378 | int cpu_mmc_init(bd_t *bis) | |
379 | { | |
380 | #ifdef CONFIG_FSL_ESDHC | |
381 | return fsl_esdhc_mmc_init(bis); | |
382 | #else | |
383 | return 0; | |
384 | #endif | |
385 | } | |
199e262e BB |
386 | |
387 | /* | |
388 | * Print out the state of various machine registers. | |
d789b5f5 DD |
389 | * Currently prints out LAWs, BR0/OR0 for LBC, CSPR/CSOR/Timing |
390 | * parameters for IFC and TLBs | |
199e262e | 391 | */ |
f3603b43 | 392 | void print_reginfo(void) |
199e262e BB |
393 | { |
394 | print_tlbcam(); | |
395 | print_laws(); | |
beba93ed | 396 | #if defined(CONFIG_FSL_LBC) |
199e262e | 397 | print_lbc_regs(); |
beba93ed | 398 | #endif |
d789b5f5 DD |
399 | #ifdef CONFIG_FSL_IFC |
400 | print_ifc_regs(); | |
401 | #endif | |
beba93ed | 402 | |
199e262e | 403 | } |
ebbe11dd | 404 | |
38dba0c2 BB |
405 | /* Common ddr init for non-corenet fsl 85xx platforms */ |
406 | #ifndef CONFIG_FSL_CORENET | |
c97cd1ba SW |
407 | #if (defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_SPL)) && \ |
408 | !defined(CONFIG_SYS_INIT_L2_ADDR) | |
f1683aa7 | 409 | int dram_init(void) |
c1fc2d4f | 410 | { |
fa08d395 | 411 | #if defined(CONFIG_SPD_EEPROM) || defined(CONFIG_DDR_SPD) || \ |
10343403 | 412 | defined(CONFIG_ARCH_QEMU_E500) |
088454cd | 413 | gd->ram_size = fsl_ddr_sdram_size(); |
c1fc2d4f | 414 | #else |
088454cd | 415 | gd->ram_size = (phys_size_t)CONFIG_SYS_SDRAM_SIZE * 1024 * 1024; |
c1fc2d4f | 416 | #endif |
088454cd SG |
417 | |
418 | return 0; | |
c1fc2d4f ZC |
419 | } |
420 | #else /* CONFIG_SYS_RAMBOOT */ | |
f1683aa7 | 421 | int dram_init(void) |
38dba0c2 BB |
422 | { |
423 | phys_size_t dram_size = 0; | |
424 | ||
810c4427 | 425 | #if defined(CONFIG_SYS_FSL_ERRATUM_DDR_MSYNC_IN) |
38dba0c2 BB |
426 | { |
427 | ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); | |
428 | unsigned int x = 10; | |
429 | unsigned int i; | |
430 | ||
431 | /* | |
432 | * Work around to stabilize DDR DLL | |
433 | */ | |
434 | out_be32(&gur->ddrdllcr, 0x81000000); | |
435 | asm("sync;isync;msync"); | |
436 | udelay(200); | |
437 | while (in_be32(&gur->ddrdllcr) != 0x81000100) { | |
438 | setbits_be32(&gur->devdisr, 0x00010000); | |
439 | for (i = 0; i < x; i++) | |
440 | ; | |
441 | clrbits_be32(&gur->devdisr, 0x00010000); | |
442 | x++; | |
443 | } | |
444 | } | |
445 | #endif | |
446 | ||
1b3e3c4f YS |
447 | #if defined(CONFIG_SPD_EEPROM) || \ |
448 | defined(CONFIG_DDR_SPD) || \ | |
449 | defined(CONFIG_SYS_DDR_RAW_TIMING) | |
38dba0c2 BB |
450 | dram_size = fsl_ddr_sdram(); |
451 | #else | |
452 | dram_size = fixed_sdram(); | |
453 | #endif | |
454 | dram_size = setup_ddr_tlbs(dram_size / 0x100000); | |
455 | dram_size *= 0x100000; | |
456 | ||
457 | #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER) | |
458 | /* | |
459 | * Initialize and enable DDR ECC. | |
460 | */ | |
461 | ddr_enable_ecc(dram_size); | |
462 | #endif | |
463 | ||
beba93ed | 464 | #if defined(CONFIG_FSL_LBC) |
38dba0c2 | 465 | /* Some boards also have sdram on the lbc */ |
70961ba4 | 466 | lbc_sdram_init(); |
beba93ed | 467 | #endif |
38dba0c2 | 468 | |
21cd5815 | 469 | debug("DDR: "); |
088454cd SG |
470 | gd->ram_size = dram_size; |
471 | ||
472 | return 0; | |
38dba0c2 | 473 | } |
c1fc2d4f | 474 | #endif /* CONFIG_SYS_RAMBOOT */ |
38dba0c2 BB |
475 | #endif |
476 | ||
ebbe11dd YS |
477 | #if CONFIG_POST & CONFIG_SYS_POST_MEMORY |
478 | ||
479 | /* Board-specific functions defined in each board's ddr.c */ | |
480 | void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd, | |
1d71efbb | 481 | unsigned int ctrl_num, unsigned int dimm_slots_per_ctrl); |
ebbe11dd YS |
482 | void read_tlbcam_entry(int idx, u32 *valid, u32 *tsize, unsigned long *epn, |
483 | phys_addr_t *rpn); | |
484 | unsigned int | |
485 | setup_ddr_tlbs_phys(phys_addr_t p_addr, unsigned int memsize_in_meg); | |
486 | ||
9cdfe281 BB |
487 | void clear_ddr_tlbs_phys(phys_addr_t p_addr, unsigned int memsize_in_meg); |
488 | ||
ebbe11dd YS |
489 | static void dump_spd_ddr_reg(void) |
490 | { | |
491 | int i, j, k, m; | |
492 | u8 *p_8; | |
493 | u32 *p_32; | |
51370d56 | 494 | struct ccsr_ddr __iomem *ddr[CONFIG_SYS_NUM_DDR_CTLRS]; |
ebbe11dd | 495 | generic_spd_eeprom_t |
51370d56 | 496 | spd[CONFIG_SYS_NUM_DDR_CTLRS][CONFIG_DIMM_SLOTS_PER_CTLR]; |
ebbe11dd | 497 | |
51370d56 | 498 | for (i = 0; i < CONFIG_SYS_NUM_DDR_CTLRS; i++) |
1d71efbb | 499 | fsl_ddr_get_spd(spd[i], i, CONFIG_DIMM_SLOTS_PER_CTLR); |
ebbe11dd | 500 | |
fc0b5948 | 501 | puts("SPD data of all dimms (zero value is omitted)...\n"); |
ebbe11dd YS |
502 | puts("Byte (hex) "); |
503 | k = 1; | |
51370d56 | 504 | for (i = 0; i < CONFIG_SYS_NUM_DDR_CTLRS; i++) { |
ebbe11dd YS |
505 | for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) |
506 | printf("Dimm%d ", k++); | |
507 | } | |
508 | puts("\n"); | |
509 | for (k = 0; k < sizeof(generic_spd_eeprom_t); k++) { | |
510 | m = 0; | |
511 | printf("%3d (0x%02x) ", k, k); | |
51370d56 | 512 | for (i = 0; i < CONFIG_SYS_NUM_DDR_CTLRS; i++) { |
ebbe11dd YS |
513 | for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { |
514 | p_8 = (u8 *) &spd[i][j]; | |
515 | if (p_8[k]) { | |
516 | printf("0x%02x ", p_8[k]); | |
517 | m++; | |
518 | } else | |
519 | puts(" "); | |
520 | } | |
521 | } | |
522 | if (m) | |
523 | puts("\n"); | |
524 | else | |
525 | puts("\r"); | |
526 | } | |
527 | ||
51370d56 | 528 | for (i = 0; i < CONFIG_SYS_NUM_DDR_CTLRS; i++) { |
ebbe11dd YS |
529 | switch (i) { |
530 | case 0: | |
5614e71b | 531 | ddr[i] = (void *)CONFIG_SYS_FSL_DDR_ADDR; |
ebbe11dd | 532 | break; |
51370d56 | 533 | #if defined(CONFIG_SYS_FSL_DDR2_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 1) |
ebbe11dd | 534 | case 1: |
5614e71b | 535 | ddr[i] = (void *)CONFIG_SYS_FSL_DDR2_ADDR; |
ebbe11dd | 536 | break; |
a4c66509 | 537 | #endif |
51370d56 | 538 | #if defined(CONFIG_SYS_FSL_DDR3_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 2) |
a4c66509 | 539 | case 2: |
5614e71b | 540 | ddr[i] = (void *)CONFIG_SYS_FSL_DDR3_ADDR; |
a4c66509 YS |
541 | break; |
542 | #endif | |
51370d56 | 543 | #if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 3) |
a4c66509 | 544 | case 3: |
5614e71b | 545 | ddr[i] = (void *)CONFIG_SYS_FSL_DDR4_ADDR; |
a4c66509 | 546 | break; |
ebbe11dd YS |
547 | #endif |
548 | default: | |
549 | printf("%s unexpected controller number = %u\n", | |
550 | __func__, i); | |
551 | return; | |
552 | } | |
553 | } | |
554 | printf("DDR registers dump for all controllers " | |
fc0b5948 | 555 | "(zero value is omitted)...\n"); |
ebbe11dd | 556 | puts("Offset (hex) "); |
51370d56 | 557 | for (i = 0; i < CONFIG_SYS_NUM_DDR_CTLRS; i++) |
ebbe11dd YS |
558 | printf(" Base + 0x%04x", (u32)ddr[i] & 0xFFFF); |
559 | puts("\n"); | |
9a17eb5b | 560 | for (k = 0; k < sizeof(struct ccsr_ddr)/4; k++) { |
ebbe11dd YS |
561 | m = 0; |
562 | printf("%6d (0x%04x)", k * 4, k * 4); | |
51370d56 | 563 | for (i = 0; i < CONFIG_SYS_NUM_DDR_CTLRS; i++) { |
ebbe11dd YS |
564 | p_32 = (u32 *) ddr[i]; |
565 | if (p_32[k]) { | |
566 | printf(" 0x%08x", p_32[k]); | |
567 | m++; | |
568 | } else | |
569 | puts(" "); | |
570 | } | |
571 | if (m) | |
572 | puts("\n"); | |
573 | else | |
574 | puts("\r"); | |
575 | } | |
576 | puts("\n"); | |
577 | } | |
578 | ||
579 | /* invalid the TLBs for DDR and setup new ones to cover p_addr */ | |
580 | static int reset_tlb(phys_addr_t p_addr, u32 size, phys_addr_t *phys_offset) | |
581 | { | |
582 | u32 vstart = CONFIG_SYS_DDR_SDRAM_BASE; | |
583 | unsigned long epn; | |
584 | u32 tsize, valid, ptr; | |
ebbe11dd YS |
585 | int ddr_esel; |
586 | ||
9cdfe281 | 587 | clear_ddr_tlbs_phys(p_addr, size>>20); |
ebbe11dd YS |
588 | |
589 | /* Setup new tlb to cover the physical address */ | |
590 | setup_ddr_tlbs_phys(p_addr, size>>20); | |
591 | ||
592 | ptr = vstart; | |
593 | ddr_esel = find_tlb_idx((void *)ptr, 1); | |
594 | if (ddr_esel != -1) { | |
595 | read_tlbcam_entry(ddr_esel, &valid, &tsize, &epn, phys_offset); | |
596 | } else { | |
597 | printf("TLB error in function %s\n", __func__); | |
598 | return -1; | |
599 | } | |
600 | ||
601 | return 0; | |
602 | } | |
603 | ||
604 | /* | |
605 | * slide the testing window up to test another area | |
606 | * for 32_bit system, the maximum testable memory is limited to | |
607 | * CONFIG_MAX_MEM_MAPPED | |
608 | */ | |
609 | int arch_memory_test_advance(u32 *vstart, u32 *size, phys_addr_t *phys_offset) | |
610 | { | |
611 | phys_addr_t test_cap, p_addr; | |
612 | phys_size_t p_size = min(gd->ram_size, CONFIG_MAX_MEM_MAPPED); | |
613 | ||
614 | #if !defined(CONFIG_PHYS_64BIT) || \ | |
615 | !defined(CONFIG_SYS_INIT_RAM_ADDR_PHYS) || \ | |
616 | (CONFIG_SYS_INIT_RAM_ADDR_PHYS < 0x100000000ull) | |
617 | test_cap = p_size; | |
618 | #else | |
619 | test_cap = gd->ram_size; | |
620 | #endif | |
621 | p_addr = (*vstart) + (*size) + (*phys_offset); | |
622 | if (p_addr < test_cap - 1) { | |
623 | p_size = min(test_cap - p_addr, CONFIG_MAX_MEM_MAPPED); | |
624 | if (reset_tlb(p_addr, p_size, phys_offset) == -1) | |
625 | return -1; | |
626 | *vstart = CONFIG_SYS_DDR_SDRAM_BASE; | |
627 | *size = (u32) p_size; | |
628 | printf("Testing 0x%08llx - 0x%08llx\n", | |
629 | (u64)(*vstart) + (*phys_offset), | |
630 | (u64)(*vstart) + (*phys_offset) + (*size) - 1); | |
631 | } else | |
632 | return 1; | |
633 | ||
634 | return 0; | |
635 | } | |
636 | ||
637 | /* initialization for testing area */ | |
638 | int arch_memory_test_prepare(u32 *vstart, u32 *size, phys_addr_t *phys_offset) | |
639 | { | |
640 | phys_size_t p_size = min(gd->ram_size, CONFIG_MAX_MEM_MAPPED); | |
641 | ||
642 | *vstart = CONFIG_SYS_DDR_SDRAM_BASE; | |
643 | *size = (u32) p_size; /* CONFIG_MAX_MEM_MAPPED < 4G */ | |
644 | *phys_offset = 0; | |
645 | ||
646 | #if !defined(CONFIG_PHYS_64BIT) || \ | |
647 | !defined(CONFIG_SYS_INIT_RAM_ADDR_PHYS) || \ | |
648 | (CONFIG_SYS_INIT_RAM_ADDR_PHYS < 0x100000000ull) | |
649 | if (gd->ram_size > CONFIG_MAX_MEM_MAPPED) { | |
650 | puts("Cannot test more than "); | |
651 | print_size(CONFIG_MAX_MEM_MAPPED, | |
652 | " without proper 36BIT support.\n"); | |
653 | } | |
654 | #endif | |
655 | printf("Testing 0x%08llx - 0x%08llx\n", | |
656 | (u64)(*vstart) + (*phys_offset), | |
657 | (u64)(*vstart) + (*phys_offset) + (*size) - 1); | |
658 | ||
659 | return 0; | |
660 | } | |
661 | ||
662 | /* invalid TLBs for DDR and remap as normal after testing */ | |
663 | int arch_memory_test_cleanup(u32 *vstart, u32 *size, phys_addr_t *phys_offset) | |
664 | { | |
665 | unsigned long epn; | |
666 | u32 tsize, valid, ptr; | |
667 | phys_addr_t rpn = 0; | |
668 | int ddr_esel; | |
669 | ||
670 | /* disable the TLBs for this testing */ | |
671 | ptr = *vstart; | |
672 | ||
673 | while (ptr < (*vstart) + (*size)) { | |
674 | ddr_esel = find_tlb_idx((void *)ptr, 1); | |
675 | if (ddr_esel != -1) { | |
676 | read_tlbcam_entry(ddr_esel, &valid, &tsize, &epn, &rpn); | |
677 | disable_tlb(ddr_esel); | |
678 | } | |
679 | ptr += TSIZE_TO_BYTES(tsize); | |
680 | } | |
681 | ||
682 | puts("Remap DDR "); | |
683 | setup_ddr_tlbs(gd->ram_size>>20); | |
684 | puts("\n"); | |
685 | ||
686 | return 0; | |
687 | } | |
688 | ||
689 | void arch_memory_failure_handle(void) | |
690 | { | |
691 | dump_spd_ddr_reg(); | |
692 | } | |
693 | #endif |