1
2
3
4
5
6
7
8#include <common.h>
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137#include <post.h>
138#include <watchdog.h>
139
140#if CONFIG_POST & (CONFIG_SYS_POST_MEMORY | CONFIG_SYS_POST_MEM_REGIONS)
141
142DECLARE_GLOBAL_DATA_PTR;
143
144
145
146
147
148#undef INJECT_DATA_ERRORS
149#undef INJECT_ADDRESS_ERRORS
150
151#ifdef INJECT_DATA_ERRORS
152#warning "Injecting data line errors for testing purposes"
153#endif
154
155#ifdef INJECT_ADDRESS_ERRORS
156#warning "Injecting address line errors for testing purposes"
157#endif
158
159
160
161
162
163
164
165
166
167
168
169
170
171static void move64(const unsigned long long *src, unsigned long long *dest)
172{
173#if defined(CONFIG_MPC8260)
174 asm ("lfd 0, 0(3)\n\t"
175 "stfd 0, 0(4)"
176 : : : "fr0" );
177 return;
178#else
179 *dest = *src;
180#endif
181}
182
183
184
185
186
187
188
189
190
191
192const static unsigned long long pattern[] = {
193 0xaaaaaaaaaaaaaaaaULL,
194 0xccccccccccccccccULL,
195 0xf0f0f0f0f0f0f0f0ULL,
196 0xff00ff00ff00ff00ULL,
197 0xffff0000ffff0000ULL,
198 0xffffffff00000000ULL,
199 0x00000000ffffffffULL,
200 0x0000ffff0000ffffULL,
201 0x00ff00ff00ff00ffULL,
202 0x0f0f0f0f0f0f0f0fULL,
203 0x3333333333333333ULL,
204 0x5555555555555555ULL
205};
206const unsigned long long otherpattern = 0x0123456789abcdefULL;
207
208
209static int memory_post_dataline(unsigned long long * pmem)
210{
211 unsigned long long temp64 = 0;
212 int num_patterns = ARRAY_SIZE(pattern);
213 int i;
214 unsigned int hi, lo, pathi, patlo;
215 int ret = 0;
216
217 for ( i = 0; i < num_patterns; i++) {
218 move64(&(pattern[i]), pmem++);
219
220
221
222
223 move64(&otherpattern, pmem--);
224 move64(pmem, &temp64);
225
226#ifdef INJECT_DATA_ERRORS
227 temp64 ^= 0x00008000;
228#endif
229
230 if (temp64 != pattern[i]){
231 pathi = (pattern[i]>>32) & 0xffffffff;
232 patlo = pattern[i] & 0xffffffff;
233
234 hi = (temp64>>32) & 0xffffffff;
235 lo = temp64 & 0xffffffff;
236
237 post_log("Memory (date line) error at %08x, "
238 "wrote %08x%08x, read %08x%08x !\n",
239 pmem, pathi, patlo, hi, lo);
240 ret = -1;
241 }
242 }
243 return ret;
244}
245
246static int memory_post_addrline(ulong *testaddr, ulong *base, ulong size)
247{
248 ulong *target;
249 ulong *end;
250 ulong readback;
251 ulong xor;
252 int ret = 0;
253
254 end = (ulong *)((ulong)base + size);
255 xor = 0;
256 for(xor = sizeof(ulong); xor > 0; xor <<= 1) {
257 target = (ulong *)((ulong)testaddr ^ xor);
258 if((target >= base) && (target < end)) {
259 *testaddr = ~*target;
260 readback = *target;
261
262#ifdef INJECT_ADDRESS_ERRORS
263 if(xor == 0x00008000) {
264 readback = *testaddr;
265 }
266#endif
267 if(readback == *testaddr) {
268 post_log("Memory (address line) error at %08x<->%08x, "
269 "XOR value %08x !\n",
270 testaddr, target, xor);
271 ret = -1;
272 }
273 }
274 }
275 return ret;
276}
277
278static int memory_post_test1(unsigned long start,
279 unsigned long size,
280 unsigned long val)
281{
282 unsigned long i;
283 ulong *mem = (ulong *) start;
284 ulong readback;
285 int ret = 0;
286
287 for (i = 0; i < size / sizeof (ulong); i++) {
288 mem[i] = val;
289 if (i % 1024 == 0)
290 WATCHDOG_RESET();
291 }
292
293 for (i = 0; i < size / sizeof (ulong) && !ret; i++) {
294 readback = mem[i];
295 if (readback != val) {
296 post_log("Memory error at %08x, "
297 "wrote %08x, read %08x !\n",
298 mem + i, val, readback);
299
300 ret = -1;
301 break;
302 }
303 if (i % 1024 == 0)
304 WATCHDOG_RESET();
305 }
306
307 return ret;
308}
309
310static int memory_post_test2(unsigned long start, unsigned long size)
311{
312 unsigned long i;
313 ulong *mem = (ulong *) start;
314 ulong readback;
315 int ret = 0;
316
317 for (i = 0; i < size / sizeof (ulong); i++) {
318 mem[i] = 1 << (i % 32);
319 if (i % 1024 == 0)
320 WATCHDOG_RESET();
321 }
322
323 for (i = 0; i < size / sizeof (ulong) && !ret; i++) {
324 readback = mem[i];
325 if (readback != (1 << (i % 32))) {
326 post_log("Memory error at %08x, "
327 "wrote %08x, read %08x !\n",
328 mem + i, 1 << (i % 32), readback);
329
330 ret = -1;
331 break;
332 }
333 if (i % 1024 == 0)
334 WATCHDOG_RESET();
335 }
336
337 return ret;
338}
339
340static int memory_post_test3(unsigned long start, unsigned long size)
341{
342 unsigned long i;
343 ulong *mem = (ulong *) start;
344 ulong readback;
345 int ret = 0;
346
347 for (i = 0; i < size / sizeof (ulong); i++) {
348 mem[i] = i;
349 if (i % 1024 == 0)
350 WATCHDOG_RESET();
351 }
352
353 for (i = 0; i < size / sizeof (ulong) && !ret; i++) {
354 readback = mem[i];
355 if (readback != i) {
356 post_log("Memory error at %08x, "
357 "wrote %08x, read %08x !\n",
358 mem + i, i, readback);
359
360 ret = -1;
361 break;
362 }
363 if (i % 1024 == 0)
364 WATCHDOG_RESET();
365 }
366
367 return ret;
368}
369
370static int memory_post_test4(unsigned long start, unsigned long size)
371{
372 unsigned long i;
373 ulong *mem = (ulong *) start;
374 ulong readback;
375 int ret = 0;
376
377 for (i = 0; i < size / sizeof (ulong); i++) {
378 mem[i] = ~i;
379 if (i % 1024 == 0)
380 WATCHDOG_RESET();
381 }
382
383 for (i = 0; i < size / sizeof (ulong) && !ret; i++) {
384 readback = mem[i];
385 if (readback != ~i) {
386 post_log("Memory error at %08x, "
387 "wrote %08x, read %08x !\n",
388 mem + i, ~i, readback);
389
390 ret = -1;
391 break;
392 }
393 if (i % 1024 == 0)
394 WATCHDOG_RESET();
395 }
396
397 return ret;
398}
399
400static int memory_post_test_lines(unsigned long start, unsigned long size)
401{
402 int ret = 0;
403
404 ret = memory_post_dataline((unsigned long long *)start);
405 WATCHDOG_RESET();
406 if (!ret)
407 ret = memory_post_addrline((ulong *)start, (ulong *)start,
408 size);
409 WATCHDOG_RESET();
410 if (!ret)
411 ret = memory_post_addrline((ulong *)(start+size-8),
412 (ulong *)start, size);
413 WATCHDOG_RESET();
414
415 return ret;
416}
417
418static int memory_post_test_patterns(unsigned long start, unsigned long size)
419{
420 int ret = 0;
421
422 ret = memory_post_test1(start, size, 0x00000000);
423 WATCHDOG_RESET();
424 if (!ret)
425 ret = memory_post_test1(start, size, 0xffffffff);
426 WATCHDOG_RESET();
427 if (!ret)
428 ret = memory_post_test1(start, size, 0x55555555);
429 WATCHDOG_RESET();
430 if (!ret)
431 ret = memory_post_test1(start, size, 0xaaaaaaaa);
432 WATCHDOG_RESET();
433 if (!ret)
434 ret = memory_post_test2(start, size);
435 WATCHDOG_RESET();
436 if (!ret)
437 ret = memory_post_test3(start, size);
438 WATCHDOG_RESET();
439 if (!ret)
440 ret = memory_post_test4(start, size);
441 WATCHDOG_RESET();
442
443 return ret;
444}
445
446static int memory_post_test_regions(unsigned long start, unsigned long size)
447{
448 unsigned long i;
449 int ret = 0;
450
451 for (i = 0; i < (size >> 20) && (!ret); i++) {
452 if (!ret)
453 ret = memory_post_test_patterns(start + (i << 20),
454 0x800);
455 if (!ret)
456 ret = memory_post_test_patterns(start + (i << 20) +
457 0xff800, 0x800);
458 }
459
460 return ret;
461}
462
463static int memory_post_tests(unsigned long start, unsigned long size)
464{
465 int ret = 0;
466
467 ret = memory_post_test_lines(start, size);
468 if (!ret)
469 ret = memory_post_test_patterns(start, size);
470
471 return ret;
472}
473
474
475
476
477__attribute__((weak))
478int arch_memory_test_prepare(u32 *vstart, u32 *size, phys_addr_t *phys_offset)
479{
480 bd_t *bd = gd->bd;
481
482 *vstart = CONFIG_SYS_SDRAM_BASE;
483 *size = (gd->ram_size >= 256 << 20 ?
484 256 << 20 : gd->ram_size) - (1 << 20);
485
486
487 if ((*vstart) + (*size) > (ulong)bd)
488 *size = (ulong)bd - *vstart;
489
490 return 0;
491}
492
493__attribute__((weak))
494int arch_memory_test_advance(u32 *vstart, u32 *size, phys_addr_t *phys_offset)
495{
496 return 1;
497}
498
499__attribute__((weak))
500int arch_memory_test_cleanup(u32 *vstart, u32 *size, phys_addr_t *phys_offset)
501{
502 return 0;
503}
504
505__attribute__((weak))
506void arch_memory_failure_handle(void)
507{
508 return;
509}
510
511int memory_regions_post_test(int flags)
512{
513 int ret = 0;
514 phys_addr_t phys_offset = 0;
515 u32 memsize, vstart;
516
517 arch_memory_test_prepare(&vstart, &memsize, &phys_offset);
518
519 ret = memory_post_test_lines(vstart, memsize);
520 if (!ret)
521 ret = memory_post_test_regions(vstart, memsize);
522
523 return ret;
524}
525
526int memory_post_test(int flags)
527{
528 int ret = 0;
529 phys_addr_t phys_offset = 0;
530 u32 memsize, vstart;
531
532 arch_memory_test_prepare(&vstart, &memsize, &phys_offset);
533
534 do {
535 if (flags & POST_SLOWTEST) {
536 ret = memory_post_tests(vstart, memsize);
537 } else {
538 ret = memory_post_test_regions(vstart, memsize);
539 }
540 } while (!ret &&
541 !arch_memory_test_advance(&vstart, &memsize, &phys_offset));
542
543 arch_memory_test_cleanup(&vstart, &memsize, &phys_offset);
544 if (ret)
545 arch_memory_failure_handle();
546
547 return ret;
548}
549
550#endif
551