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