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