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 *dest = *src;
174}
175
176
177
178
179
180
181
182
183
184
185const static unsigned long long pattern[] = {
186 0xaaaaaaaaaaaaaaaaULL,
187 0xccccccccccccccccULL,
188 0xf0f0f0f0f0f0f0f0ULL,
189 0xff00ff00ff00ff00ULL,
190 0xffff0000ffff0000ULL,
191 0xffffffff00000000ULL,
192 0x00000000ffffffffULL,
193 0x0000ffff0000ffffULL,
194 0x00ff00ff00ff00ffULL,
195 0x0f0f0f0f0f0f0f0fULL,
196 0x3333333333333333ULL,
197 0x5555555555555555ULL
198};
199const unsigned long long otherpattern = 0x0123456789abcdefULL;
200
201
202static int memory_post_dataline(unsigned long long * pmem)
203{
204 unsigned long long temp64 = 0;
205 int num_patterns = ARRAY_SIZE(pattern);
206 int i;
207 unsigned int hi, lo, pathi, patlo;
208 int ret = 0;
209
210 for ( i = 0; i < num_patterns; i++) {
211 move64(&(pattern[i]), pmem++);
212
213
214
215
216 move64(&otherpattern, pmem--);
217 move64(pmem, &temp64);
218
219#ifdef INJECT_DATA_ERRORS
220 temp64 ^= 0x00008000;
221#endif
222
223 if (temp64 != pattern[i]){
224 pathi = (pattern[i]>>32) & 0xffffffff;
225 patlo = pattern[i] & 0xffffffff;
226
227 hi = (temp64>>32) & 0xffffffff;
228 lo = temp64 & 0xffffffff;
229
230 post_log("Memory (data line) error at %08x, "
231 "wrote %08x%08x, read %08x%08x !\n",
232 pmem, pathi, patlo, hi, lo);
233 ret = -1;
234 }
235 }
236 return ret;
237}
238
239static int memory_post_addrline(ulong *testaddr, ulong *base, ulong size)
240{
241 ulong *target;
242 ulong *end;
243 ulong readback;
244 ulong xor;
245 int ret = 0;
246
247 end = (ulong *)((ulong)base + size);
248 xor = 0;
249 for(xor = sizeof(ulong); xor > 0; xor <<= 1) {
250 target = (ulong *)((ulong)testaddr ^ xor);
251 if((target >= base) && (target < end)) {
252 *testaddr = ~*target;
253 readback = *target;
254
255#ifdef INJECT_ADDRESS_ERRORS
256 if(xor == 0x00008000) {
257 readback = *testaddr;
258 }
259#endif
260 if(readback == *testaddr) {
261 post_log("Memory (address line) error at %08x<->%08x, "
262 "XOR value %08x !\n",
263 testaddr, target, xor);
264 ret = -1;
265 }
266 }
267 }
268 return ret;
269}
270
271static int memory_post_test1(unsigned long start,
272 unsigned long size,
273 unsigned long val)
274{
275 unsigned long i;
276 ulong *mem = (ulong *) start;
277 ulong readback;
278 int ret = 0;
279
280 for (i = 0; i < size / sizeof (ulong); i++) {
281 mem[i] = val;
282 if (i % 1024 == 0)
283 WATCHDOG_RESET();
284 }
285
286 for (i = 0; i < size / sizeof (ulong) && !ret; i++) {
287 readback = mem[i];
288 if (readback != val) {
289 post_log("Memory error at %08x, "
290 "wrote %08x, read %08x !\n",
291 mem + i, val, readback);
292
293 ret = -1;
294 break;
295 }
296 if (i % 1024 == 0)
297 WATCHDOG_RESET();
298 }
299
300 return ret;
301}
302
303static int memory_post_test2(unsigned long start, unsigned long size)
304{
305 unsigned long i;
306 ulong *mem = (ulong *) start;
307 ulong readback;
308 int ret = 0;
309
310 for (i = 0; i < size / sizeof (ulong); i++) {
311 mem[i] = 1 << (i % 32);
312 if (i % 1024 == 0)
313 WATCHDOG_RESET();
314 }
315
316 for (i = 0; i < size / sizeof (ulong) && !ret; i++) {
317 readback = mem[i];
318 if (readback != (1 << (i % 32))) {
319 post_log("Memory error at %08x, "
320 "wrote %08x, read %08x !\n",
321 mem + i, 1 << (i % 32), readback);
322
323 ret = -1;
324 break;
325 }
326 if (i % 1024 == 0)
327 WATCHDOG_RESET();
328 }
329
330 return ret;
331}
332
333static int memory_post_test3(unsigned long start, unsigned long size)
334{
335 unsigned long i;
336 ulong *mem = (ulong *) start;
337 ulong readback;
338 int ret = 0;
339
340 for (i = 0; i < size / sizeof (ulong); i++) {
341 mem[i] = i;
342 if (i % 1024 == 0)
343 WATCHDOG_RESET();
344 }
345
346 for (i = 0; i < size / sizeof (ulong) && !ret; i++) {
347 readback = mem[i];
348 if (readback != i) {
349 post_log("Memory error at %08x, "
350 "wrote %08x, read %08x !\n",
351 mem + i, i, readback);
352
353 ret = -1;
354 break;
355 }
356 if (i % 1024 == 0)
357 WATCHDOG_RESET();
358 }
359
360 return ret;
361}
362
363static int memory_post_test4(unsigned long start, unsigned long size)
364{
365 unsigned long i;
366 ulong *mem = (ulong *) start;
367 ulong readback;
368 int ret = 0;
369
370 for (i = 0; i < size / sizeof (ulong); i++) {
371 mem[i] = ~i;
372 if (i % 1024 == 0)
373 WATCHDOG_RESET();
374 }
375
376 for (i = 0; i < size / sizeof (ulong) && !ret; i++) {
377 readback = mem[i];
378 if (readback != ~i) {
379 post_log("Memory error at %08x, "
380 "wrote %08x, read %08x !\n",
381 mem + i, ~i, readback);
382
383 ret = -1;
384 break;
385 }
386 if (i % 1024 == 0)
387 WATCHDOG_RESET();
388 }
389
390 return ret;
391}
392
393static int memory_post_test_lines(unsigned long start, unsigned long size)
394{
395 int ret = 0;
396
397 ret = memory_post_dataline((unsigned long long *)start);
398 WATCHDOG_RESET();
399 if (!ret)
400 ret = memory_post_addrline((ulong *)start, (ulong *)start,
401 size);
402 WATCHDOG_RESET();
403 if (!ret)
404 ret = memory_post_addrline((ulong *)(start+size-8),
405 (ulong *)start, size);
406 WATCHDOG_RESET();
407
408 return ret;
409}
410
411static int memory_post_test_patterns(unsigned long start, unsigned long size)
412{
413 int ret = 0;
414
415 ret = memory_post_test1(start, size, 0x00000000);
416 WATCHDOG_RESET();
417 if (!ret)
418 ret = memory_post_test1(start, size, 0xffffffff);
419 WATCHDOG_RESET();
420 if (!ret)
421 ret = memory_post_test1(start, size, 0x55555555);
422 WATCHDOG_RESET();
423 if (!ret)
424 ret = memory_post_test1(start, size, 0xaaaaaaaa);
425 WATCHDOG_RESET();
426 if (!ret)
427 ret = memory_post_test2(start, size);
428 WATCHDOG_RESET();
429 if (!ret)
430 ret = memory_post_test3(start, size);
431 WATCHDOG_RESET();
432 if (!ret)
433 ret = memory_post_test4(start, size);
434 WATCHDOG_RESET();
435
436 return ret;
437}
438
439static int memory_post_test_regions(unsigned long start, unsigned long size)
440{
441 unsigned long i;
442 int ret = 0;
443
444 for (i = 0; i < (size >> 20) && (!ret); i++) {
445 if (!ret)
446 ret = memory_post_test_patterns(start + (i << 20),
447 0x800);
448 if (!ret)
449 ret = memory_post_test_patterns(start + (i << 20) +
450 0xff800, 0x800);
451 }
452
453 return ret;
454}
455
456static int memory_post_tests(unsigned long start, unsigned long size)
457{
458 int ret = 0;
459
460 ret = memory_post_test_lines(start, size);
461 if (!ret)
462 ret = memory_post_test_patterns(start, size);
463
464 return ret;
465}
466
467
468
469
470__attribute__((weak))
471int arch_memory_test_prepare(u32 *vstart, u32 *size, phys_addr_t *phys_offset)
472{
473 bd_t *bd = gd->bd;
474
475 *vstart = CONFIG_SYS_SDRAM_BASE;
476 *size = (gd->ram_size >= 256 << 20 ?
477 256 << 20 : gd->ram_size) - (1 << 20);
478
479
480 if ((*vstart) + (*size) > (ulong)bd)
481 *size = (ulong)bd - *vstart;
482
483 return 0;
484}
485
486__attribute__((weak))
487int arch_memory_test_advance(u32 *vstart, u32 *size, phys_addr_t *phys_offset)
488{
489 return 1;
490}
491
492__attribute__((weak))
493int arch_memory_test_cleanup(u32 *vstart, u32 *size, phys_addr_t *phys_offset)
494{
495 return 0;
496}
497
498__attribute__((weak))
499void arch_memory_failure_handle(void)
500{
501 return;
502}
503
504int memory_regions_post_test(int flags)
505{
506 int ret = 0;
507 phys_addr_t phys_offset = 0;
508 u32 memsize, vstart;
509
510 arch_memory_test_prepare(&vstart, &memsize, &phys_offset);
511
512 ret = memory_post_test_lines(vstart, memsize);
513 if (!ret)
514 ret = memory_post_test_regions(vstart, memsize);
515
516 return ret;
517}
518
519int memory_post_test(int flags)
520{
521 int ret = 0;
522 phys_addr_t phys_offset = 0;
523 u32 memsize, vstart;
524
525 arch_memory_test_prepare(&vstart, &memsize, &phys_offset);
526
527 do {
528 if (flags & POST_SLOWTEST) {
529 ret = memory_post_tests(vstart, memsize);
530 } else {
531 ret = memory_post_test_regions(vstart, memsize);
532 }
533 } while (!ret &&
534 !arch_memory_test_advance(&vstart, &memsize, &phys_offset));
535
536 arch_memory_test_cleanup(&vstart, &memsize, &phys_offset);
537 if (ret)
538 arch_memory_failure_handle();
539
540 return ret;
541}
542
543#endif
544