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