Commit a724a9b40c7fbeb6ade193ca52321b441eaecb4e

Authored by Larry Johnson
Committed by Stefan Roese
1 parent 454a6cf8d4

Fix/enhance ECC POST for 440EPx/GRx

This patch allows the ECC POST to be used for different boards with the
PPC440 Denali SDRAM controller.  Modifications include skipping the test
if ECC is not enabled (as for non-ECC DIMMs) and adding synchronization
to prevent timing errors.

Signed-off-by: Larry Johnson <lrj@acm.org>

Showing 2 changed files with 46 additions and 46 deletions Side-by-side Diff

post/cpu/ppc4xx/Makefile
... ... @@ -24,7 +24,7 @@
24 24 LIB = libpostppc4xx.a
25 25  
26 26 AOBJS = cache_4xx.o
27   -COBJS = cache.o ether.o fpu.o spr.o uart.o watchdog.o
  27 +COBJS = cache.o denali_ecc.o ether.o fpu.o spr.o uart.o watchdog.o
28 28  
29 29 include $(TOPDIR)/post/rules.mk
post/cpu/ppc4xx/denali_ecc.c
... ... @@ -31,7 +31,7 @@
31 31 #include <common.h>
32 32 #include <watchdog.h>
33 33  
34   -#ifdef CONFIG_POST
  34 +#if defined(CONFIG_POST) && (defined(CONFIG_440EPX) || defined(CONFIG_440GRX))
35 35  
36 36 #include <post.h>
37 37  
... ... @@ -47,8 +47,6 @@
47 47 #include <asm/io.h>
48 48 #include <ppc440.h>
49 49  
50   -#include "../../../board/lwmon5/sdram.h"
51   -
52 50 DECLARE_GLOBAL_DATA_PTR;
53 51  
54 52 const static unsigned char syndrome_codes[] = {
... ... @@ -65,9 +63,9 @@
65 63  
66 64 #define ECC_START_ADDR 0x10
67 65 #define ECC_STOP_ADDR 0x2000
68   -#define ECC_PATTERN 0x0101010101010101ull
69   -#define ECC_PATTERN_CORR 0x0101010101010100ull
70   -#define ECC_PATTERN_UNCORR 0x010101010101010Full
  66 +#define ECC_PATTERN 0x01010101
  67 +#define ECC_PATTERN_CORR 0x11010101
  68 +#define ECC_PATTERN_UNCORR 0xF1010101
71 69  
72 70 static int test_ecc_error(void)
73 71 {
74 72  
75 73  
76 74  
77 75  
78 76  
79 77  
80 78  
81 79  
82 80  
83 81  
84 82  
85 83  
86 84  
87 85  
88 86  
89 87  
... ... @@ -152,68 +150,78 @@
152 150  
153 151 static int test_ecc(unsigned long ecc_addr)
154 152 {
155   - volatile unsigned long long *ecc_mem;
156 153 unsigned long value;
157   - unsigned long ecc_data;
158   - volatile unsigned long *lecc_mem;
159   - int pret, ret = 0;
  154 + volatile unsigned *const ecc_mem = (volatile unsigned *) ecc_addr;
  155 + int pret;
  156 + int ret = 0;
160 157  
161 158 sync();
162 159 eieio();
163 160 WATCHDOG_RESET();
164 161  
165   - ecc_mem = (unsigned long long *)ecc_addr;
166   - lecc_mem = (ulong *)ecc_addr;
167   - *ecc_mem = ECC_PATTERN;
  162 + debug("Entering test_ecc(0x%08lX)\n", ecc_addr);
  163 + out_be32(ecc_mem, ECC_PATTERN);
  164 + out_be32(ecc_mem + 1, ECC_PATTERN);
  165 + in_be32(ecc_mem);
168 166 pret = test_ecc_error();
169   - if (pret != 0)
  167 + if (pret != 0) {
  168 + debug("pret: expected 0, got %d\n", pret);
170 169 ret = 1;
171   -
172   - /* disconnect ecc */
  170 + }
  171 + /* test for correctable error */
  172 + /* disconnect from ecc storage */
173 173 mfsdram(DDR0_22, value);
174 174 mtsdram(DDR0_22, (value &~ DDR0_22_CTRL_RAW_MASK)
175 175 | DDR0_22_CTRL_RAW_ECC_DISABLE);
176 176  
177   - /* injecting error */
178   - *ecc_mem = ECC_PATTERN_CORR;
  177 + /* creating (correctable) single-bit error */
  178 + out_be32(ecc_mem, ECC_PATTERN_CORR);
179 179  
180 180 /* enable ecc */
181 181 mfsdram(DDR0_22, value);
182 182 mtsdram(DDR0_22, (value &~ DDR0_22_CTRL_RAW_MASK)
183 183 | DDR0_22_CTRL_RAW_ECC_ENABLE);
  184 + sync();
  185 + eieio();
184 186  
185   - ecc_data = *lecc_mem;
  187 + in_be32(ecc_mem);
186 188 pret = test_ecc_error();
187 189 /* if read data ok, 1 correctable error must be fixed */
188   - if (pret != 3)
  190 + if (pret != 3) {
  191 + debug("pret: expected 3, got %d\n", pret);
189 192 ret = 1;
190   -
  193 + }
191 194 /* test for uncorrectable error */
192 195 /* disconnect from ecc storage */
193 196 mfsdram(DDR0_22, value);
194 197 mtsdram(DDR0_22, (value &~ DDR0_22_CTRL_RAW_MASK)
195 198 | DDR0_22_CTRL_RAW_NO_ECC_RAM);
196 199  
197   - /* injecting multiply bit error */
  200 + /* creating (uncorrectable) multiple-bit error */
  201 + out_be32(ecc_mem, ECC_PATTERN_UNCORR);
198 202  
199   - *ecc_mem = ECC_PATTERN_UNCORR;
200   -
201 203 /* enable ecc */
202 204 mfsdram(DDR0_22, value);
203 205 mtsdram(DDR0_22, (value &~ DDR0_22_CTRL_RAW_MASK)
204 206 | DDR0_22_CTRL_RAW_ECC_ENABLE);
  207 + sync();
  208 + eieio();
205 209  
206   - ecc_data = *lecc_mem;
207   - /* what the data should be read? */
208   -
  210 + in_be32(ecc_mem);
209 211 pret = test_ecc_error();
210 212 /* info about uncorrectable error must appear */
211   - if (pret != 5)
  213 + if (pret != 5) {
  214 + debug("pret: expected 5, got %d\n", pret);
212 215 ret = 1;
  216 + }
  217 + /* remove error from SDRAM */
  218 + out_be32(ecc_mem, ECC_PATTERN);
  219 + /* clear error caused by read-modify-write */
  220 + mfsdram(DDR0_00, value);
  221 + mtsdram(DDR0_00, value | DDR0_00_INT_ACK_ALL);
213 222  
214 223 sync();
215 224 eieio();
216   -
217 225 return ret;
218 226 }
219 227  
220 228  
... ... @@ -223,10 +231,15 @@
223 231 unsigned long value;
224 232 unsigned long iaddr;
225 233  
226   -#if CONFIG_DDR_ECC
227 234 sync();
228 235 eieio();
229 236  
  237 + mfsdram(DDR0_22, value);
  238 + if (0x3 != DDR0_22_CTRL_RAW_DECODE(value)) {
  239 + debug("SDRAM ECC not enabled, skipping ECC POST.\n");
  240 + return 0;
  241 + }
  242 +
230 243 /* mask all int */
231 244 mfsdram(DDR0_01, value);
232 245 mtsdram(DDR0_01, (value &~ DDR0_01_INT_MASK_MASK)
233 246  
234 247  
235 248  
236 249  
... ... @@ -236,33 +249,20 @@
236 249 mfsdram(DDR0_00, value);
237 250 mtsdram(DDR0_00, value | DDR0_00_INT_ACK_ALL);
238 251  
239   - /* enable full support of ECC */
240   - mfsdram(DDR0_22, value);
241   - mtsdram(DDR0_22, (value &~ DDR0_22_CTRL_RAW_MASK)
242   - | DDR0_22_CTRL_RAW_ECC_ENABLE);
243   -
244   - for (iaddr = ECC_START_ADDR; iaddr < ECC_STOP_ADDR; iaddr += iaddr) {
  252 + for (iaddr = ECC_START_ADDR; iaddr <= ECC_STOP_ADDR; iaddr += iaddr) {
245 253 ret = test_ecc(iaddr);
246 254 if (ret)
247 255 break;
248 256 }
249   -
250   - /* clear error status */
251   - mfsdram(DDR0_00, value);
252   - mtsdram(DDR0_00, value | DDR0_00_INT_ACK_ALL);
253   -
254 257 /*
255 258 * Clear possible errors resulting from ECC testing.
256 259 * If not done, then we could get an interrupt later on when
257 260 * exceptions are enabled.
258 261 */
259 262 set_mcsr(get_mcsr());
260   -#endif
261   -
262 263 return ret;
263 264  
264 265 }
265   -
266 266 #endif /* CONFIG_POST & CFG_POST_ECC */
267   -#endif /* CONFIG_POST */
  267 +#endif /* defined(CONFIG_POST) && ... */