]>
Commit | Line | Data |
---|---|---|
5f820439 DL |
1 | /* |
2 | * Copyright (C) 2006 Freescale Semiconductor, Inc. | |
3 | * | |
4 | * Dave Liu <daveliu@freescale.com> | |
5 | * based on board/mpc8349emds/mpc8349emds.c | |
6 | * | |
7 | * See file CREDITS for list of people who contributed to this | |
8 | * project. | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or | |
11 | * modify it under the terms of the GNU General Public License as | |
12 | * published by the Free Software Foundation; either version 2 of | |
13 | * the License, or (at your option) any later version. | |
14 | */ | |
15 | ||
16 | #include <common.h> | |
17 | #include <ioports.h> | |
18 | #include <mpc83xx.h> | |
19 | #include <i2c.h> | |
20 | #include <spd.h> | |
21 | #include <miiphy.h> | |
22 | #include <command.h> | |
23 | #if defined(CONFIG_PCI) | |
24 | #include <pci.h> | |
25 | #endif | |
26 | #if defined(CONFIG_SPD_EEPROM) | |
27 | #include <spd_sdram.h> | |
28 | #else | |
29 | #include <asm/mmu.h> | |
30 | #endif | |
bf0b542d KP |
31 | #if defined(CONFIG_OF_FLAT_TREE) |
32 | #include <ft_build.h> | |
33 | #endif | |
213bf8c8 GVB |
34 | #if defined(CONFIG_OF_LIBFDT) |
35 | #include <libfdt.h> | |
36 | #include <libfdt_env.h> | |
37 | #endif | |
5f820439 | 38 | |
7737d5c6 DL |
39 | const qe_iop_conf_t qe_iop_conf_tab[] = { |
40 | /* GETH1 */ | |
41 | {0, 3, 1, 0, 1}, /* TxD0 */ | |
42 | {0, 4, 1, 0, 1}, /* TxD1 */ | |
43 | {0, 5, 1, 0, 1}, /* TxD2 */ | |
44 | {0, 6, 1, 0, 1}, /* TxD3 */ | |
45 | {1, 6, 1, 0, 3}, /* TxD4 */ | |
46 | {1, 7, 1, 0, 1}, /* TxD5 */ | |
47 | {1, 9, 1, 0, 2}, /* TxD6 */ | |
48 | {1, 10, 1, 0, 2}, /* TxD7 */ | |
49 | {0, 9, 2, 0, 1}, /* RxD0 */ | |
50 | {0, 10, 2, 0, 1}, /* RxD1 */ | |
51 | {0, 11, 2, 0, 1}, /* RxD2 */ | |
52 | {0, 12, 2, 0, 1}, /* RxD3 */ | |
53 | {0, 13, 2, 0, 1}, /* RxD4 */ | |
54 | {1, 1, 2, 0, 2}, /* RxD5 */ | |
55 | {1, 0, 2, 0, 2}, /* RxD6 */ | |
56 | {1, 4, 2, 0, 2}, /* RxD7 */ | |
57 | {0, 7, 1, 0, 1}, /* TX_EN */ | |
58 | {0, 8, 1, 0, 1}, /* TX_ER */ | |
59 | {0, 15, 2, 0, 1}, /* RX_DV */ | |
60 | {0, 16, 2, 0, 1}, /* RX_ER */ | |
61 | {0, 0, 2, 0, 1}, /* RX_CLK */ | |
62 | {2, 9, 1, 0, 3}, /* GTX_CLK - CLK10 */ | |
63 | {2, 8, 2, 0, 1}, /* GTX125 - CLK9 */ | |
64 | /* GETH2 */ | |
65 | {0, 17, 1, 0, 1}, /* TxD0 */ | |
66 | {0, 18, 1, 0, 1}, /* TxD1 */ | |
67 | {0, 19, 1, 0, 1}, /* TxD2 */ | |
68 | {0, 20, 1, 0, 1}, /* TxD3 */ | |
69 | {1, 2, 1, 0, 1}, /* TxD4 */ | |
70 | {1, 3, 1, 0, 2}, /* TxD5 */ | |
71 | {1, 5, 1, 0, 3}, /* TxD6 */ | |
72 | {1, 8, 1, 0, 3}, /* TxD7 */ | |
73 | {0, 23, 2, 0, 1}, /* RxD0 */ | |
74 | {0, 24, 2, 0, 1}, /* RxD1 */ | |
75 | {0, 25, 2, 0, 1}, /* RxD2 */ | |
76 | {0, 26, 2, 0, 1}, /* RxD3 */ | |
77 | {0, 27, 2, 0, 1}, /* RxD4 */ | |
78 | {1, 12, 2, 0, 2}, /* RxD5 */ | |
79 | {1, 13, 2, 0, 3}, /* RxD6 */ | |
80 | {1, 11, 2, 0, 2}, /* RxD7 */ | |
81 | {0, 21, 1, 0, 1}, /* TX_EN */ | |
82 | {0, 22, 1, 0, 1}, /* TX_ER */ | |
83 | {0, 29, 2, 0, 1}, /* RX_DV */ | |
84 | {0, 30, 2, 0, 1}, /* RX_ER */ | |
85 | {0, 31, 2, 0, 1}, /* RX_CLK */ | |
86 | {2, 2, 1, 0, 2}, /* GTX_CLK = CLK10 */ | |
87 | {2, 3, 2, 0, 1}, /* GTX125 - CLK4 */ | |
88 | ||
89 | {0, 1, 3, 0, 2}, /* MDIO */ | |
90 | {0, 2, 1, 0, 1}, /* MDC */ | |
91 | ||
92 | {0, 0, 0, 0, QE_IOP_TAB_END}, /* END of table */ | |
93 | }; | |
94 | ||
5f820439 DL |
95 | int board_early_init_f(void) |
96 | { | |
3fc0bd15 KP |
97 | |
98 | u8 *bcsr = (u8 *)CFG_BCSR; | |
99 | const immap_t *immr = (immap_t *)CFG_IMMR; | |
5f820439 DL |
100 | |
101 | /* Enable flash write */ | |
102 | bcsr[0xa] &= ~0x04; | |
103 | ||
3fc0bd15 KP |
104 | /* Disable G1TXCLK, G2TXCLK h/w buffers (rev.2 h/w bug workaround) */ |
105 | if (immr->sysconf.spridr == SPR_8360_REV20 || | |
106 | immr->sysconf.spridr == SPR_8360E_REV20) | |
107 | bcsr[0xe] = 0x30; | |
108 | ||
5f820439 DL |
109 | return 0; |
110 | } | |
111 | ||
112 | #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRC) | |
113 | extern void ddr_enable_ecc(unsigned int dram_size); | |
114 | #endif | |
115 | int fixed_sdram(void); | |
116 | void sdram_init(void); | |
117 | ||
118 | long int initdram(int board_type) | |
119 | { | |
d239d74b | 120 | volatile immap_t *im = (immap_t *) CFG_IMMR; |
5f820439 DL |
121 | u32 msize = 0; |
122 | ||
123 | if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im) | |
124 | return -1; | |
125 | ||
126 | /* DDR SDRAM - Main SODIMM */ | |
127 | im->sysconf.ddrlaw[0].bar = CFG_DDR_BASE & LAWBAR_BAR; | |
128 | #if defined(CONFIG_SPD_EEPROM) | |
129 | msize = spd_sdram(); | |
130 | #else | |
131 | msize = fixed_sdram(); | |
132 | #endif | |
133 | ||
134 | #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRC) | |
135 | /* | |
136 | * Initialize DDR ECC byte | |
137 | */ | |
138 | ddr_enable_ecc(msize * 1024 * 1024); | |
139 | #endif | |
140 | /* | |
141 | * Initialize SDRAM if it is on local bus. | |
142 | */ | |
143 | sdram_init(); | |
144 | puts(" DDR RAM: "); | |
145 | /* return total bus SDRAM size(bytes) -- DDR */ | |
146 | return (msize * 1024 * 1024); | |
147 | } | |
148 | ||
149 | #if !defined(CONFIG_SPD_EEPROM) | |
150 | /************************************************************************* | |
151 | * fixed sdram init -- doesn't use serial presence detect. | |
152 | ************************************************************************/ | |
153 | int fixed_sdram(void) | |
154 | { | |
d239d74b | 155 | volatile immap_t *im = (immap_t *) CFG_IMMR; |
5f820439 DL |
156 | u32 msize = 0; |
157 | u32 ddr_size; | |
158 | u32 ddr_size_log2; | |
159 | ||
160 | msize = CFG_DDR_SIZE; | |
161 | for (ddr_size = msize << 20, ddr_size_log2 = 0; | |
162 | (ddr_size > 1); ddr_size = ddr_size >> 1, ddr_size_log2++) { | |
163 | if (ddr_size & 1) { | |
164 | return -1; | |
165 | } | |
166 | } | |
167 | im->sysconf.ddrlaw[0].ar = | |
168 | LAWAR_EN | ((ddr_size_log2 - 1) & LAWAR_SIZE); | |
169 | #if (CFG_DDR_SIZE != 256) | |
170 | #warning Currenly any ddr size other than 256 is not supported | |
171 | #endif | |
d61853cf XX |
172 | #ifdef CONFIG_DDR_II |
173 | im->ddr.csbnds[0].csbnds = CFG_DDR_CS0_BNDS; | |
174 | im->ddr.cs_config[0] = CFG_DDR_CS0_CONFIG; | |
175 | im->ddr.timing_cfg_0 = CFG_DDR_TIMING_0; | |
176 | im->ddr.timing_cfg_1 = CFG_DDR_TIMING_1; | |
177 | im->ddr.timing_cfg_2 = CFG_DDR_TIMING_2; | |
178 | im->ddr.timing_cfg_3 = CFG_DDR_TIMING_3; | |
179 | im->ddr.sdram_cfg = CFG_DDR_SDRAM_CFG; | |
180 | im->ddr.sdram_cfg2 = CFG_DDR_SDRAM_CFG2; | |
181 | im->ddr.sdram_mode = CFG_DDR_MODE; | |
182 | im->ddr.sdram_mode2 = CFG_DDR_MODE2; | |
183 | im->ddr.sdram_interval = CFG_DDR_INTERVAL; | |
184 | im->ddr.sdram_clk_cntl = CFG_DDR_CLK_CNTL; | |
185 | #else | |
5f820439 DL |
186 | im->ddr.csbnds[0].csbnds = 0x00000007; |
187 | im->ddr.csbnds[1].csbnds = 0x0008000f; | |
188 | ||
189 | im->ddr.cs_config[0] = CFG_DDR_CONFIG; | |
190 | im->ddr.cs_config[1] = CFG_DDR_CONFIG; | |
191 | ||
192 | im->ddr.timing_cfg_1 = CFG_DDR_TIMING_1; | |
193 | im->ddr.timing_cfg_2 = CFG_DDR_TIMING_2; | |
194 | im->ddr.sdram_cfg = CFG_DDR_CONTROL; | |
195 | ||
196 | im->ddr.sdram_mode = CFG_DDR_MODE; | |
197 | im->ddr.sdram_interval = CFG_DDR_INTERVAL; | |
d61853cf | 198 | #endif |
5f820439 DL |
199 | udelay(200); |
200 | im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN; | |
201 | ||
202 | return msize; | |
203 | } | |
204 | #endif /*!CFG_SPD_EEPROM */ | |
205 | ||
206 | int checkboard(void) | |
207 | { | |
208 | puts("Board: Freescale MPC8360EMDS\n"); | |
209 | return 0; | |
210 | } | |
211 | ||
212 | /* | |
213 | * if MPC8360EMDS is soldered with SDRAM | |
214 | */ | |
215 | #if defined(CFG_BR2_PRELIM) \ | |
216 | && defined(CFG_OR2_PRELIM) \ | |
217 | && defined(CFG_LBLAWBAR2_PRELIM) \ | |
218 | && defined(CFG_LBLAWAR2_PRELIM) | |
219 | /* | |
220 | * Initialize SDRAM memory on the Local Bus. | |
221 | */ | |
222 | ||
223 | void sdram_init(void) | |
224 | { | |
d239d74b | 225 | volatile immap_t *immap = (immap_t *) CFG_IMMR; |
5f820439 DL |
226 | volatile lbus83xx_t *lbc = &immap->lbus; |
227 | uint *sdram_addr = (uint *) CFG_LBC_SDRAM_BASE; | |
228 | ||
229 | puts("\n SDRAM on Local Bus: "); | |
230 | print_size(CFG_LBC_SDRAM_SIZE * 1024 * 1024, "\n"); | |
231 | /* | |
232 | * Setup SDRAM Base and Option Registers, already done in cpu_init.c | |
233 | */ | |
234 | /*setup mtrpt, lsrt and lbcr for LB bus */ | |
235 | lbc->lbcr = CFG_LBC_LBCR; | |
236 | lbc->mrtpr = CFG_LBC_MRTPR; | |
237 | lbc->lsrt = CFG_LBC_LSRT; | |
238 | asm("sync"); | |
239 | ||
240 | /* | |
241 | * Configure the SDRAM controller Machine Mode Register. | |
242 | */ | |
243 | lbc->lsdmr = CFG_LBC_LSDMR_5; /* Normal Operation */ | |
244 | lbc->lsdmr = CFG_LBC_LSDMR_1; /* Precharge All Banks */ | |
245 | asm("sync"); | |
246 | *sdram_addr = 0xff; | |
247 | udelay(100); | |
248 | ||
249 | /* | |
250 | * We need do 8 times auto refresh operation. | |
251 | */ | |
252 | lbc->lsdmr = CFG_LBC_LSDMR_2; | |
253 | asm("sync"); | |
254 | *sdram_addr = 0xff; /* 1 times */ | |
255 | udelay(100); | |
256 | *sdram_addr = 0xff; /* 2 times */ | |
257 | udelay(100); | |
258 | *sdram_addr = 0xff; /* 3 times */ | |
259 | udelay(100); | |
260 | *sdram_addr = 0xff; /* 4 times */ | |
261 | udelay(100); | |
262 | *sdram_addr = 0xff; /* 5 times */ | |
263 | udelay(100); | |
264 | *sdram_addr = 0xff; /* 6 times */ | |
265 | udelay(100); | |
266 | *sdram_addr = 0xff; /* 7 times */ | |
267 | udelay(100); | |
268 | *sdram_addr = 0xff; /* 8 times */ | |
269 | udelay(100); | |
270 | ||
271 | /* Mode register write operation */ | |
272 | lbc->lsdmr = CFG_LBC_LSDMR_4; | |
273 | asm("sync"); | |
274 | *(sdram_addr + 0xcc) = 0xff; | |
275 | udelay(100); | |
276 | ||
277 | /* Normal operation */ | |
278 | lbc->lsdmr = CFG_LBC_LSDMR_5 | 0x40000000; | |
279 | asm("sync"); | |
280 | *sdram_addr = 0xff; | |
281 | udelay(100); | |
282 | } | |
283 | #else | |
284 | void sdram_init(void) | |
285 | { | |
286 | puts("SDRAM on Local Bus is NOT available!\n"); | |
287 | } | |
288 | #endif | |
289 | ||
290 | #if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD) | |
291 | /* | |
292 | * ECC user commands | |
293 | */ | |
294 | void ecc_print_status(void) | |
295 | { | |
d239d74b | 296 | volatile immap_t *immap = (immap_t *) CFG_IMMR; |
5f820439 DL |
297 | volatile ddr83xx_t *ddr = &immap->ddr; |
298 | ||
299 | printf("\nECC mode: %s\n\n", | |
300 | (ddr->sdram_cfg & SDRAM_CFG_ECC_EN) ? "ON" : "OFF"); | |
301 | ||
302 | /* Interrupts */ | |
303 | printf("Memory Error Interrupt Enable:\n"); | |
304 | printf(" Multiple-Bit Error Interrupt Enable: %d\n", | |
305 | (ddr->err_int_en & ECC_ERR_INT_EN_MBEE) ? 1 : 0); | |
306 | printf(" Single-Bit Error Interrupt Enable: %d\n", | |
307 | (ddr->err_int_en & ECC_ERR_INT_EN_SBEE) ? 1 : 0); | |
308 | printf(" Memory Select Error Interrupt Enable: %d\n\n", | |
309 | (ddr->err_int_en & ECC_ERR_INT_EN_MSEE) ? 1 : 0); | |
310 | ||
311 | /* Error disable */ | |
312 | printf("Memory Error Disable:\n"); | |
313 | printf(" Multiple-Bit Error Disable: %d\n", | |
314 | (ddr->err_disable & ECC_ERROR_DISABLE_MBED) ? 1 : 0); | |
315 | printf(" Sinle-Bit Error Disable: %d\n", | |
316 | (ddr->err_disable & ECC_ERROR_DISABLE_SBED) ? 1 : 0); | |
317 | printf(" Memory Select Error Disable: %d\n\n", | |
318 | (ddr->err_disable & ECC_ERROR_DISABLE_MSED) ? 1 : 0); | |
319 | ||
320 | /* Error injection */ | |
321 | printf("Memory Data Path Error Injection Mask High/Low: %08lx %08lx\n", | |
322 | ddr->data_err_inject_hi, ddr->data_err_inject_lo); | |
323 | ||
324 | printf("Memory Data Path Error Injection Mask ECC:\n"); | |
325 | printf(" ECC Mirror Byte: %d\n", | |
326 | (ddr->ecc_err_inject & ECC_ERR_INJECT_EMB) ? 1 : 0); | |
327 | printf(" ECC Injection Enable: %d\n", | |
328 | (ddr->ecc_err_inject & ECC_ERR_INJECT_EIEN) ? 1 : 0); | |
329 | printf(" ECC Error Injection Mask: 0x%02x\n\n", | |
330 | ddr->ecc_err_inject & ECC_ERR_INJECT_EEIM); | |
331 | ||
332 | /* SBE counter/threshold */ | |
333 | printf("Memory Single-Bit Error Management (0..255):\n"); | |
334 | printf(" Single-Bit Error Threshold: %d\n", | |
335 | (ddr->err_sbe & ECC_ERROR_MAN_SBET) >> ECC_ERROR_MAN_SBET_SHIFT); | |
336 | printf(" Single-Bit Error Counter: %d\n\n", | |
337 | (ddr->err_sbe & ECC_ERROR_MAN_SBEC) >> ECC_ERROR_MAN_SBEC_SHIFT); | |
338 | ||
339 | /* Error detect */ | |
340 | printf("Memory Error Detect:\n"); | |
341 | printf(" Multiple Memory Errors: %d\n", | |
342 | (ddr->err_detect & ECC_ERROR_DETECT_MME) ? 1 : 0); | |
343 | printf(" Multiple-Bit Error: %d\n", | |
344 | (ddr->err_detect & ECC_ERROR_DETECT_MBE) ? 1 : 0); | |
345 | printf(" Single-Bit Error: %d\n", | |
346 | (ddr->err_detect & ECC_ERROR_DETECT_SBE) ? 1 : 0); | |
347 | printf(" Memory Select Error: %d\n\n", | |
348 | (ddr->err_detect & ECC_ERROR_DETECT_MSE) ? 1 : 0); | |
349 | ||
350 | /* Capture data */ | |
351 | printf("Memory Error Address Capture: 0x%08lx\n", ddr->capture_address); | |
352 | printf("Memory Data Path Read Capture High/Low: %08lx %08lx\n", | |
353 | ddr->capture_data_hi, ddr->capture_data_lo); | |
354 | printf("Memory Data Path Read Capture ECC: 0x%02x\n\n", | |
355 | ddr->capture_ecc & CAPTURE_ECC_ECE); | |
356 | ||
357 | printf("Memory Error Attributes Capture:\n"); | |
358 | printf(" Data Beat Number: %d\n", | |
359 | (ddr->capture_attributes & ECC_CAPT_ATTR_BNUM) >> | |
360 | ECC_CAPT_ATTR_BNUM_SHIFT); | |
361 | printf(" Transaction Size: %d\n", | |
362 | (ddr->capture_attributes & ECC_CAPT_ATTR_TSIZ) >> | |
363 | ECC_CAPT_ATTR_TSIZ_SHIFT); | |
364 | printf(" Transaction Source: %d\n", | |
365 | (ddr->capture_attributes & ECC_CAPT_ATTR_TSRC) >> | |
366 | ECC_CAPT_ATTR_TSRC_SHIFT); | |
367 | printf(" Transaction Type: %d\n", | |
368 | (ddr->capture_attributes & ECC_CAPT_ATTR_TTYP) >> | |
369 | ECC_CAPT_ATTR_TTYP_SHIFT); | |
370 | printf(" Error Information Valid: %d\n\n", | |
371 | ddr->capture_attributes & ECC_CAPT_ATTR_VLD); | |
372 | } | |
373 | ||
374 | int do_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) | |
375 | { | |
d239d74b | 376 | volatile immap_t *immap = (immap_t *) CFG_IMMR; |
5f820439 DL |
377 | volatile ddr83xx_t *ddr = &immap->ddr; |
378 | volatile u32 val; | |
379 | u64 *addr; | |
380 | u32 count; | |
381 | register u64 *i; | |
382 | u32 ret[2]; | |
383 | u32 pattern[2]; | |
384 | u32 writeback[2]; | |
385 | ||
386 | /* The pattern is written into memory to generate error */ | |
387 | pattern[0] = 0xfedcba98UL; | |
388 | pattern[1] = 0x76543210UL; | |
389 | ||
390 | /* After injecting error, re-initialize the memory with the value */ | |
391 | writeback[0] = 0x01234567UL; | |
392 | writeback[1] = 0x89abcdefUL; | |
393 | ||
394 | if (argc > 4) { | |
395 | printf("Usage:\n%s\n", cmdtp->usage); | |
396 | return 1; | |
397 | } | |
398 | ||
399 | if (argc == 2) { | |
400 | if (strcmp(argv[1], "status") == 0) { | |
401 | ecc_print_status(); | |
402 | return 0; | |
403 | } else if (strcmp(argv[1], "captureclear") == 0) { | |
404 | ddr->capture_address = 0; | |
405 | ddr->capture_data_hi = 0; | |
406 | ddr->capture_data_lo = 0; | |
407 | ddr->capture_ecc = 0; | |
408 | ddr->capture_attributes = 0; | |
409 | return 0; | |
410 | } | |
411 | } | |
412 | if (argc == 3) { | |
413 | if (strcmp(argv[1], "sbecnt") == 0) { | |
414 | val = simple_strtoul(argv[2], NULL, 10); | |
415 | if (val > 255) { | |
416 | printf("Incorrect Counter value, " | |
417 | "should be 0..255\n"); | |
418 | return 1; | |
419 | } | |
420 | ||
421 | val = (val << ECC_ERROR_MAN_SBEC_SHIFT); | |
422 | val |= (ddr->err_sbe & ECC_ERROR_MAN_SBET); | |
423 | ||
424 | ddr->err_sbe = val; | |
425 | return 0; | |
426 | } else if (strcmp(argv[1], "sbethr") == 0) { | |
427 | val = simple_strtoul(argv[2], NULL, 10); | |
428 | if (val > 255) { | |
429 | printf("Incorrect Counter value, " | |
430 | "should be 0..255\n"); | |
431 | return 1; | |
432 | } | |
433 | ||
434 | val = (val << ECC_ERROR_MAN_SBET_SHIFT); | |
435 | val |= (ddr->err_sbe & ECC_ERROR_MAN_SBEC); | |
436 | ||
437 | ddr->err_sbe = val; | |
438 | return 0; | |
439 | } else if (strcmp(argv[1], "errdisable") == 0) { | |
440 | val = ddr->err_disable; | |
441 | ||
442 | if (strcmp(argv[2], "+sbe") == 0) { | |
443 | val |= ECC_ERROR_DISABLE_SBED; | |
444 | } else if (strcmp(argv[2], "+mbe") == 0) { | |
445 | val |= ECC_ERROR_DISABLE_MBED; | |
446 | } else if (strcmp(argv[2], "+mse") == 0) { | |
447 | val |= ECC_ERROR_DISABLE_MSED; | |
448 | } else if (strcmp(argv[2], "+all") == 0) { | |
449 | val |= (ECC_ERROR_DISABLE_SBED | | |
450 | ECC_ERROR_DISABLE_MBED | | |
451 | ECC_ERROR_DISABLE_MSED); | |
452 | } else if (strcmp(argv[2], "-sbe") == 0) { | |
453 | val &= ~ECC_ERROR_DISABLE_SBED; | |
454 | } else if (strcmp(argv[2], "-mbe") == 0) { | |
455 | val &= ~ECC_ERROR_DISABLE_MBED; | |
456 | } else if (strcmp(argv[2], "-mse") == 0) { | |
457 | val &= ~ECC_ERROR_DISABLE_MSED; | |
458 | } else if (strcmp(argv[2], "-all") == 0) { | |
459 | val &= ~(ECC_ERROR_DISABLE_SBED | | |
460 | ECC_ERROR_DISABLE_MBED | | |
461 | ECC_ERROR_DISABLE_MSED); | |
462 | } else { | |
463 | printf("Incorrect err_disable field\n"); | |
464 | return 1; | |
465 | } | |
466 | ||
467 | ddr->err_disable = val; | |
468 | __asm__ __volatile__("sync"); | |
469 | __asm__ __volatile__("isync"); | |
470 | return 0; | |
471 | } else if (strcmp(argv[1], "errdetectclr") == 0) { | |
472 | val = ddr->err_detect; | |
473 | ||
474 | if (strcmp(argv[2], "mme") == 0) { | |
475 | val |= ECC_ERROR_DETECT_MME; | |
476 | } else if (strcmp(argv[2], "sbe") == 0) { | |
477 | val |= ECC_ERROR_DETECT_SBE; | |
478 | } else if (strcmp(argv[2], "mbe") == 0) { | |
479 | val |= ECC_ERROR_DETECT_MBE; | |
480 | } else if (strcmp(argv[2], "mse") == 0) { | |
481 | val |= ECC_ERROR_DETECT_MSE; | |
482 | } else if (strcmp(argv[2], "all") == 0) { | |
483 | val |= (ECC_ERROR_DETECT_MME | | |
484 | ECC_ERROR_DETECT_MBE | | |
485 | ECC_ERROR_DETECT_SBE | | |
486 | ECC_ERROR_DETECT_MSE); | |
487 | } else { | |
488 | printf("Incorrect err_detect field\n"); | |
489 | return 1; | |
490 | } | |
491 | ||
492 | ddr->err_detect = val; | |
493 | return 0; | |
494 | } else if (strcmp(argv[1], "injectdatahi") == 0) { | |
495 | val = simple_strtoul(argv[2], NULL, 16); | |
496 | ||
497 | ddr->data_err_inject_hi = val; | |
498 | return 0; | |
499 | } else if (strcmp(argv[1], "injectdatalo") == 0) { | |
500 | val = simple_strtoul(argv[2], NULL, 16); | |
501 | ||
502 | ddr->data_err_inject_lo = val; | |
503 | return 0; | |
504 | } else if (strcmp(argv[1], "injectecc") == 0) { | |
505 | val = simple_strtoul(argv[2], NULL, 16); | |
506 | if (val > 0xff) { | |
507 | printf("Incorrect ECC inject mask, " | |
508 | "should be 0x00..0xff\n"); | |
509 | return 1; | |
510 | } | |
511 | val |= (ddr->ecc_err_inject & ~ECC_ERR_INJECT_EEIM); | |
512 | ||
513 | ddr->ecc_err_inject = val; | |
514 | return 0; | |
515 | } else if (strcmp(argv[1], "inject") == 0) { | |
516 | val = ddr->ecc_err_inject; | |
517 | ||
518 | if (strcmp(argv[2], "en") == 0) | |
519 | val |= ECC_ERR_INJECT_EIEN; | |
520 | else if (strcmp(argv[2], "dis") == 0) | |
521 | val &= ~ECC_ERR_INJECT_EIEN; | |
522 | else | |
523 | printf("Incorrect command\n"); | |
524 | ||
525 | ddr->ecc_err_inject = val; | |
526 | __asm__ __volatile__("sync"); | |
527 | __asm__ __volatile__("isync"); | |
528 | return 0; | |
529 | } else if (strcmp(argv[1], "mirror") == 0) { | |
530 | val = ddr->ecc_err_inject; | |
531 | ||
532 | if (strcmp(argv[2], "en") == 0) | |
533 | val |= ECC_ERR_INJECT_EMB; | |
534 | else if (strcmp(argv[2], "dis") == 0) | |
535 | val &= ~ECC_ERR_INJECT_EMB; | |
536 | else | |
537 | printf("Incorrect command\n"); | |
538 | ||
539 | ddr->ecc_err_inject = val; | |
540 | return 0; | |
541 | } | |
542 | } | |
543 | if (argc == 4) { | |
544 | if (strcmp(argv[1], "testdw") == 0) { | |
545 | addr = (u64 *) simple_strtoul(argv[2], NULL, 16); | |
546 | count = simple_strtoul(argv[3], NULL, 16); | |
547 | ||
548 | if ((u32) addr % 8) { | |
549 | printf("Address not alligned on " | |
550 | "double word boundary\n"); | |
551 | return 1; | |
552 | } | |
553 | disable_interrupts(); | |
554 | ||
555 | for (i = addr; i < addr + count; i++) { | |
556 | ||
557 | /* enable injects */ | |
558 | ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN; | |
559 | __asm__ __volatile__("sync"); | |
560 | __asm__ __volatile__("isync"); | |
561 | ||
562 | /* write memory location injecting errors */ | |
563 | ppcDWstore((u32 *) i, pattern); | |
90f30a71 | 564 | __asm__ __volatile__("sync"); |
5f820439 DL |
565 | |
566 | /* disable injects */ | |
567 | ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN; | |
568 | __asm__ __volatile__("sync"); | |
569 | __asm__ __volatile__("isync"); | |
570 | ||
571 | /* read data, this generates ECC error */ | |
572 | ppcDWload((u32 *) i, ret); | |
90f30a71 | 573 | __asm__ __volatile__("sync"); |
5f820439 DL |
574 | |
575 | /* re-initialize memory, double word write the location again, | |
576 | * generates new ECC code this time */ | |
577 | ppcDWstore((u32 *) i, writeback); | |
90f30a71 | 578 | __asm__ __volatile__("sync"); |
5f820439 DL |
579 | } |
580 | enable_interrupts(); | |
581 | return 0; | |
582 | } | |
583 | if (strcmp(argv[1], "testword") == 0) { | |
584 | addr = (u64 *) simple_strtoul(argv[2], NULL, 16); | |
585 | count = simple_strtoul(argv[3], NULL, 16); | |
586 | ||
587 | if ((u32) addr % 8) { | |
588 | printf("Address not alligned on " | |
589 | "double word boundary\n"); | |
590 | return 1; | |
591 | } | |
592 | disable_interrupts(); | |
593 | ||
594 | for (i = addr; i < addr + count; i++) { | |
595 | ||
596 | /* enable injects */ | |
597 | ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN; | |
598 | __asm__ __volatile__("sync"); | |
599 | __asm__ __volatile__("isync"); | |
600 | ||
601 | /* write memory location injecting errors */ | |
602 | *(u32 *) i = 0xfedcba98UL; | |
603 | __asm__ __volatile__("sync"); | |
604 | ||
605 | /* sub double word write, | |
606 | * bus will read-modify-write, | |
607 | * generates ECC error */ | |
608 | *((u32 *) i + 1) = 0x76543210UL; | |
609 | __asm__ __volatile__("sync"); | |
610 | ||
611 | /* disable injects */ | |
612 | ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN; | |
613 | __asm__ __volatile__("sync"); | |
614 | __asm__ __volatile__("isync"); | |
615 | ||
616 | /* re-initialize memory, | |
617 | * double word write the location again, | |
618 | * generates new ECC code this time */ | |
619 | ppcDWstore((u32 *) i, writeback); | |
90f30a71 | 620 | __asm__ __volatile__("sync"); |
5f820439 DL |
621 | } |
622 | enable_interrupts(); | |
623 | return 0; | |
624 | } | |
625 | } | |
626 | printf("Usage:\n%s\n", cmdtp->usage); | |
627 | return 1; | |
628 | } | |
629 | ||
630 | U_BOOT_CMD(ecc, 4, 0, do_ecc, | |
631 | "ecc - support for DDR ECC features\n", | |
632 | "status - print out status info\n" | |
633 | "ecc captureclear - clear capture regs data\n" | |
634 | "ecc sbecnt <val> - set Single-Bit Error counter\n" | |
635 | "ecc sbethr <val> - set Single-Bit Threshold\n" | |
636 | "ecc errdisable <flag> - clear/set disable Memory Error Disable, flag:\n" | |
637 | " [-|+]sbe - Single-Bit Error\n" | |
638 | " [-|+]mbe - Multiple-Bit Error\n" | |
639 | " [-|+]mse - Memory Select Error\n" | |
640 | " [-|+]all - all errors\n" | |
641 | "ecc errdetectclr <flag> - clear Memory Error Detect, flag:\n" | |
642 | " mme - Multiple Memory Errors\n" | |
643 | " sbe - Single-Bit Error\n" | |
644 | " mbe - Multiple-Bit Error\n" | |
645 | " mse - Memory Select Error\n" | |
646 | " all - all errors\n" | |
647 | "ecc injectdatahi <hi> - set Memory Data Path Error Injection Mask High\n" | |
648 | "ecc injectdatalo <lo> - set Memory Data Path Error Injection Mask Low\n" | |
649 | "ecc injectecc <ecc> - set ECC Error Injection Mask\n" | |
650 | "ecc inject <en|dis> - enable/disable error injection\n" | |
651 | "ecc mirror <en|dis> - enable/disable mirror byte\n" | |
652 | "ecc testdw <addr> <cnt> - test mem region with double word access:\n" | |
653 | " - enables injects\n" | |
654 | " - writes pattern injecting errors with double word access\n" | |
655 | " - disables injects\n" | |
656 | " - reads pattern back with double word access, generates error\n" | |
657 | " - re-inits memory\n" | |
658 | "ecc testword <addr> <cnt> - test mem region with word access:\n" | |
659 | " - enables injects\n" | |
660 | " - writes pattern injecting errors with word access\n" | |
661 | " - writes pattern with word access, generates error\n" | |
662 | " - disables injects\n" " - re-inits memory"); | |
663 | #endif /* if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD) */ | |
bf0b542d | 664 | |
213bf8c8 GVB |
665 | #if (defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)) \ |
666 | && defined(CONFIG_OF_BOARD_SETUP) | |
bf0b542d KP |
667 | void |
668 | ft_board_setup(void *blob, bd_t *bd) | |
669 | { | |
213bf8c8 GVB |
670 | #if defined(CONFIG_OF_LIBFDT) |
671 | int nodeoffset; | |
672 | int err; | |
673 | int tmp[2]; | |
674 | ||
675 | nodeoffset = fdt_path_offset (fdt, "/memory"); | |
676 | if (nodeoffset >= 0) { | |
677 | tmp[0] = cpu_to_be32(bd->bi_memstart); | |
678 | tmp[1] = cpu_to_be32(bd->bi_memsize); | |
679 | err = fdt_setprop(fdt, nodeoffset, "reg", tmp, sizeof(tmp)); | |
680 | } | |
681 | #else | |
bf0b542d KP |
682 | u32 *p; |
683 | int len; | |
684 | ||
bf0b542d KP |
685 | p = ft_get_prop(blob, "/memory/reg", &len); |
686 | if (p != NULL) { | |
687 | *p++ = cpu_to_be32(bd->bi_memstart); | |
688 | *p = cpu_to_be32(bd->bi_memsize); | |
689 | } | |
213bf8c8 GVB |
690 | #endif |
691 | ||
692 | #ifdef CONFIG_PCI | |
693 | ft_pci_setup(blob, bd); | |
694 | #endif | |
695 | ft_cpu_setup(blob, bd); | |
bf0b542d KP |
696 | } |
697 | #endif |