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