]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/mpl/common/memtst.c
* Code cleanup:
[karo-tx-uboot.git] / board / mpl / common / memtst.c
1 /*
2  * (C) Copyright 2001
3  * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  *
23  */
24
25 /* NOT Used yet...
26   add following code to PIP405.c :
27 int testdram (void)
28 {
29         unsigned char s[32];
30         int i;
31
32         i = getenv_r ("testmem", s, 32);
33         if (i != 0) {
34                 i = (int) simple_strtoul (s, NULL, 10);
35                 if ((i > 0) && (i < 0xf)) {
36                         printf ("testing ");
37                         i = mem_test (0, ramsize, i);
38                         if (i > 0)
39                                 printf ("ERROR ");
40                         else
41                                 printf ("Ok ");
42                 }
43         }
44         return (1);
45 }
46 */
47
48
49 #include <common.h>
50 #include <asm/processor.h>
51 #include <405gp_i2c.h>
52
53 #define FALSE           0
54 #define TRUE            1
55
56 #define TEST_QUIET                      8
57 #define TEST_SHOW_PROG  4
58 #define TEST_SHOW_ERR   2
59 #define TEST_SHOW_ALL           1
60
61 #define TESTPAT1 0xAA55AA55
62 #define TESTPAT2 0x55AA55AA
63 #define TEST_PASSED 0
64 #define TEST_FAILED 1
65 #define MEGABYTE (1024*1024)
66
67
68 typedef struct {
69         volatile unsigned long pat1;
70         volatile unsigned long pat2;
71 } RAM_MEMTEST_PATTERN2;
72
73 typedef struct {
74         volatile unsigned long addr;
75 } RAM_MEMTEST_ADDRLINE;
76
77 static __inline unsigned long Swap_32 (unsigned long val)
78 {
79         return (((val << 16) & 0xFFFF0000) | ((val >> 16) & 0x0000FFFF));
80 }
81
82 void testm_puts (int quiet, char *buf)
83 {
84         if ((quiet & TEST_SHOW_ALL) == TEST_SHOW_ALL)
85                 puts (buf);
86 }
87
88
89 void Write_Error (int mode, unsigned long addr, unsigned long expected,
90                                   unsigned long actual)
91 {
92
93         char dispbuf[64];
94
95         sprintf (dispbuf, "\n ERROR @ 0x%08lX: (exp: 0x%08lX act: 0x%08lX) ",
96                          addr, expected, actual);
97         testm_puts (((mode & TEST_SHOW_ERR) ==
98                                  TEST_SHOW_ERR) ? TEST_SHOW_ALL : mode, dispbuf);
99 }
100
101
102 /*
103  * fills the memblock of <size> bytes from <startaddr> with pat1 and pat2
104  */
105
106
107 void RAM_MemTest_WritePattern2 (unsigned long startaddr,
108                                                                 unsigned long size, unsigned long pat1,
109                                                                 unsigned long pat2)
110 {
111         RAM_MEMTEST_PATTERN2 *p, *pe;
112
113         p = (RAM_MEMTEST_PATTERN2 *) startaddr;
114         pe = (RAM_MEMTEST_PATTERN2 *) (startaddr + size);
115
116         while (p < pe) {
117                 p->pat1 = pat1;
118                 p->pat2 = pat2;
119                 p++;
120         }                                                       /* endwhile */
121 }
122
123 /*
124  * checks the memblock of <size> bytes from <startaddr> with pat1 and pat2
125  * returns the address of the first error or NULL if all is well
126  */
127
128 void *RAM_MemTest_CheckPattern2 (int mode, unsigned long startaddr,
129                                                                  unsigned long size, unsigned long pat1,
130                                                                  unsigned long pat2)
131 {
132         RAM_MEMTEST_PATTERN2 *p, *pe;
133         unsigned long actual1, actual2;
134
135         p = (RAM_MEMTEST_PATTERN2 *) startaddr;
136         pe = (RAM_MEMTEST_PATTERN2 *) (startaddr + size);
137
138         while (p < pe) {
139                 actual1 = p->pat1;
140                 actual2 = p->pat2;
141
142                 if (actual1 != pat1) {
143                         Write_Error (mode, (unsigned long) &(p->pat1), pat1, actual1);
144                         return ((void *) &(p->pat1));
145                 }
146                 /* endif */
147                 if (actual2 != pat2) {
148                         Write_Error (mode, (unsigned long) &(p->pat2), pat2, actual2);
149                         return ((void *) &(p->pat2));
150                 }
151                 /* endif */
152                 p++;
153         }                                                       /* endwhile */
154
155         return (NULL);
156 }
157
158 /*
159  * fills the memblock of <size> bytes from <startaddr> with the address
160  */
161
162 void RAM_MemTest_WriteAddrLine (unsigned long startaddr,
163                                                                 unsigned long size, int swapped)
164 {
165         RAM_MEMTEST_ADDRLINE *p, *pe;
166
167         p = (RAM_MEMTEST_ADDRLINE *) startaddr;
168         pe = (RAM_MEMTEST_ADDRLINE *) (startaddr + size);
169
170         if (!swapped) {
171                 while (p < pe) {
172                         p->addr = (unsigned long) p;
173                         p++;
174                 }                                               /* endwhile */
175         } else {
176                 while (p < pe) {
177                         p->addr = Swap_32 ((unsigned long) p);
178                         p++;
179                 }                                               /* endwhile */
180         }                                                       /* endif */
181 }
182
183 /*
184  * checks the memblock of <size> bytes from <startaddr>
185  * returns the address of the error or NULL if all is well
186  */
187
188 void *RAM_MemTest_CheckAddrLine (int mode, unsigned long startaddr,
189                                                                  unsigned long size, int swapped)
190 {
191         RAM_MEMTEST_ADDRLINE *p, *pe;
192         unsigned long actual, expected;
193
194         p = (RAM_MEMTEST_ADDRLINE *) startaddr;
195         pe = (RAM_MEMTEST_ADDRLINE *) (startaddr + size);
196
197         if (!swapped) {
198                 while (p < pe) {
199                         actual = p->addr;
200                         expected = (unsigned long) p;
201                         if (actual != expected) {
202                                 Write_Error (mode, (unsigned long) &(p->addr), expected,
203                                                          actual);
204                                 return ((void *) &(p->addr));
205                         }                                       /* endif */
206                         p++;
207                 }                                               /* endwhile */
208         } else {
209                 while (p < pe) {
210                         actual = p->addr;
211                         expected = Swap_32 ((unsigned long) p);
212                         if (actual != expected) {
213                                 Write_Error (mode, (unsigned long) &(p->addr), expected,
214                                                          actual);
215                                 return ((void *) &(p->addr));
216                         }                                       /* endif */
217                         p++;
218                 }                                               /* endwhile */
219         }                                                       /* endif */
220
221         return (NULL);
222 }
223
224 /*
225  * checks the memblock of <size> bytes from <startaddr+size>
226  * returns the address of the error or NULL if all is well
227  */
228
229 void *RAM_MemTest_CheckAddrLineReverse (int mode, unsigned long startaddr,
230                                                                                 unsigned long size, int swapped)
231 {
232         RAM_MEMTEST_ADDRLINE *p, *pe;
233         unsigned long actual, expected;
234
235         p = (RAM_MEMTEST_ADDRLINE *) (startaddr + size - sizeof (p->addr));
236         pe = (RAM_MEMTEST_ADDRLINE *) startaddr;
237
238         if (!swapped) {
239                 while (p > pe) {
240                         actual = p->addr;
241                         expected = (unsigned long) p;
242                         if (actual != expected) {
243                                 Write_Error (mode, (unsigned long) &(p->addr), expected,
244                                                          actual);
245                                 return ((void *) &(p->addr));
246                         }                                       /* endif */
247                         p--;
248                 }                                               /* endwhile */
249         } else {
250                 while (p > pe) {
251                         actual = p->addr;
252                         expected = Swap_32 ((unsigned long) p);
253                         if (actual != expected) {
254                                 Write_Error (mode, (unsigned long) &(p->addr), expected,
255                                                          actual);
256                                 return ((void *) &(p->addr));
257                         }                                       /* endif */
258                         p--;
259                 }                                               /* endwhile */
260         }                                                       /* endif */
261
262         return (NULL);
263 }
264
265 /*
266  * fills the memblock of <size> bytes from <startaddr> with walking bit pattern
267  */
268
269 void RAM_MemTest_WriteWalkBit (unsigned long startaddr, unsigned long size)
270 {
271         volatile unsigned long *p, *pe;
272         unsigned long i;
273
274         p = (unsigned long *) startaddr;
275         pe = (unsigned long *) (startaddr + size);
276         i = 0;
277
278         while (p < pe) {
279                 *p = 1UL << i;
280                 i = (i + 1 + (((unsigned long) p) >> 7)) % 32;
281                 p++;
282         }                                                       /* endwhile */
283 }
284
285 /*
286  * checks the memblock of <size> bytes from <startaddr>
287  * returns the address of the error or NULL if all is well
288  */
289
290 void *RAM_MemTest_CheckWalkBit (int mode, unsigned long startaddr,
291                                                                 unsigned long size)
292 {
293         volatile unsigned long *p, *pe;
294         unsigned long actual, expected;
295         unsigned long i;
296
297         p = (unsigned long *) startaddr;
298         pe = (unsigned long *) (startaddr + size);
299         i = 0;
300
301         while (p < pe) {
302                 actual = *p;
303                 expected = (1UL << i);
304                 if (actual != expected) {
305                         Write_Error (mode, (unsigned long) p, expected, actual);
306                         return ((void *) p);
307                 }                                               /* endif */
308                 i = (i + 1 + (((unsigned long) p) >> 7)) % 32;
309                 p++;
310         }                                                       /* endwhile */
311
312         return (NULL);
313 }
314
315 /*
316  * fills the memblock of <size> bytes from <startaddr> with "random" pattern
317  */
318
319 void RAM_MemTest_WriteRandomPattern (unsigned long startaddr,
320                                                                          unsigned long size,
321                                                                          unsigned long *pat)
322 {
323         unsigned long i, p;
324
325         p = *pat;
326
327         for (i = 0; i < (size / 4); i++) {
328                 *(unsigned long *) (startaddr + i * 4) = p;
329                 if ((p % 2) > 0) {
330                         p ^= i;
331                         p >>= 1;
332                         p |= 0x80000000;
333                 } else {
334                         p ^= ~i;
335                         p >>= 1;
336                 }                                               /* endif */
337         }                                                       /* endfor */
338         *pat = p;
339 }
340
341 /*
342  * checks the memblock of <size> bytes from <startaddr>
343  * returns the address of the error or NULL if all is well
344  */
345
346 void *RAM_MemTest_CheckRandomPattern (int mode, unsigned long startaddr,
347                                                                           unsigned long size,
348                                                                           unsigned long *pat)
349 {
350         void *perr = NULL;
351         unsigned long i, p, p1;
352
353         p = *pat;
354
355         for (i = 0; i < (size / 4); i++) {
356                 p1 = *(unsigned long *) (startaddr + i * 4);
357                 if (p1 != p) {
358                         if (perr == NULL) {
359                                 Write_Error (mode, startaddr + i * 4, p, p1);
360                                 perr = (void *) (startaddr + i * 4);
361                         }                                       /* endif */
362                 }
363                 /* endif */
364                 if ((p % 2) > 0) {
365                         p ^= i;
366                         p >>= 1;
367                         p |= 0x80000000;
368                 } else {
369                         p ^= ~i;
370                         p >>= 1;
371                 }                                               /* endif */
372         }                                                       /* endfor */
373
374         *pat = p;
375         return (perr);
376 }
377
378
379 void RAM_MemTest_WriteData1 (unsigned long startaddr, unsigned long size,
380                                                          unsigned long *pat)
381 {
382         RAM_MemTest_WritePattern2 (startaddr, size, TESTPAT1, TESTPAT2);
383 }
384
385 void *RAM_MemTest_CheckData1 (int mode, unsigned long startaddr,
386                                                           unsigned long size, unsigned long *pat)
387 {
388         return (RAM_MemTest_CheckPattern2
389                         (mode, startaddr, size, TESTPAT1, TESTPAT2));
390 }
391
392 void RAM_MemTest_WriteData2 (unsigned long startaddr, unsigned long size,
393                                                          unsigned long *pat)
394 {
395         RAM_MemTest_WritePattern2 (startaddr, size, TESTPAT2, TESTPAT1);
396 }
397
398 void *RAM_MemTest_CheckData2 (int mode, unsigned long startaddr,
399                                                           unsigned long size, unsigned long *pat)
400 {
401         return (RAM_MemTest_CheckPattern2
402                         (mode, startaddr, size, TESTPAT2, TESTPAT1));
403 }
404
405 void RAM_MemTest_WriteAddr1 (unsigned long startaddr, unsigned long size,
406                                                          unsigned long *pat)
407 {
408         RAM_MemTest_WriteAddrLine (startaddr, size, FALSE);
409 }
410
411 void *RAM_MemTest_Check1Addr1 (int mode, unsigned long startaddr,
412                                                            unsigned long size, unsigned long *pat)
413 {
414         return (RAM_MemTest_CheckAddrLine (mode, startaddr, size, FALSE));
415 }
416
417 void *RAM_MemTest_Check2Addr1 (int mode, unsigned long startaddr,
418                                                            unsigned long size, unsigned long *pat)
419 {
420         return (RAM_MemTest_CheckAddrLineReverse
421                         (mode, startaddr, size, FALSE));
422 }
423
424 void RAM_MemTest_WriteAddr2 (unsigned long startaddr, unsigned long size,
425                                                          unsigned long *pat)
426 {
427         RAM_MemTest_WriteAddrLine (startaddr, size, TRUE);
428 }
429
430 void *RAM_MemTest_Check1Addr2 (int mode, unsigned long startaddr,
431                                                            unsigned long size, unsigned long *pat)
432 {
433         return (RAM_MemTest_CheckAddrLine (mode, startaddr, size, TRUE));
434 }
435
436 void *RAM_MemTest_Check2Addr2 (int mode, unsigned long startaddr,
437                                                            unsigned long size, unsigned long *pat)
438 {
439         return (RAM_MemTest_CheckAddrLineReverse
440                         (mode, startaddr, size, TRUE));
441 }
442
443
444 typedef struct {
445         void (*test_write) (unsigned long startaddr, unsigned long size,
446                                                 unsigned long *pat);
447         char *test_write_desc;
448         void *(*test_check1) (int mode, unsigned long startaddr,
449                                                   unsigned long size, unsigned long *pat);
450         void *(*test_check2) (int mode, unsigned long startaddr,
451                                                   unsigned long size, unsigned long *pat);
452 } RAM_MEMTEST_FUNC;
453
454
455 #define TEST_STAGES 5
456 static RAM_MEMTEST_FUNC test_stage[TEST_STAGES] = {
457         {RAM_MemTest_WriteData1, "data test 1...\n", RAM_MemTest_CheckData1,
458          NULL},
459         {RAM_MemTest_WriteData2, "data test 2...\n", RAM_MemTest_CheckData2,
460          NULL},
461         {RAM_MemTest_WriteAddr1, "address line test...\n",
462          RAM_MemTest_Check1Addr1, RAM_MemTest_Check2Addr1},
463         {RAM_MemTest_WriteAddr2, "address line test (swapped)...\n",
464          RAM_MemTest_Check1Addr2, RAM_MemTest_Check2Addr2},
465         {RAM_MemTest_WriteRandomPattern, "random data test...\n",
466          RAM_MemTest_CheckRandomPattern, NULL}
467 };
468
469 void mem_test_reloc(void)
470 {
471         DECLARE_GLOBAL_DATA_PTR;
472         unsigned long addr;
473         int i;
474         for (i=0; i< TEST_STAGES; i++) {
475                 addr = (ulong) (test_stage[i].test_write) + gd->reloc_off;
476                 test_stage[i].test_write=
477                         (void (*) (unsigned long startaddr, unsigned long size,
478                                                 unsigned long *pat))addr;
479                 addr = (ulong) (test_stage[i].test_write_desc) + gd->reloc_off;
480                 test_stage[i].test_write_desc=(char *)addr;
481                 if(test_stage[i].test_check1) {
482                         addr = (ulong) (test_stage[i].test_check1) + gd->reloc_off;
483                         test_stage[i].test_check1=
484                                 (void *(*) (int mode, unsigned long startaddr,
485                                  unsigned long size, unsigned long *pat))addr;
486                 }
487                 if(test_stage[i].test_check2) {
488                         addr = (ulong) (test_stage[i].test_check2) + gd->reloc_off;
489                         test_stage[i].test_check2=
490                                 (void *(*) (int mode, unsigned long startaddr,
491                                  unsigned long size, unsigned long *pat))addr;
492                 }
493         }
494 }
495
496
497 int mem_test (unsigned long start, unsigned long ramsize, int quiet, int reloc)
498 {
499         unsigned long errors, stage;
500         unsigned long startaddr, size, i;
501         const unsigned long blocksize = 0x80000;        /* check in 512KB blocks */
502         unsigned long *perr;
503         unsigned long rdatapat;
504         char dispbuf[80];
505         int status = TEST_PASSED;
506         int prog = 0;
507
508         errors = 0;
509         startaddr = start;
510         size = ramsize;
511         if ((quiet & TEST_SHOW_PROG) == TEST_SHOW_PROG) {
512                 prog++;
513                 printf (".");
514         }
515         sprintf (dispbuf, "\nMemory Test: addr = 0x%lx size = 0x%lx\n",
516                          startaddr, size);
517         testm_puts (quiet, dispbuf);
518         for (stage = 0; stage < TEST_STAGES; stage++) {
519                 sprintf (dispbuf, test_stage[stage].test_write_desc);
520                 testm_puts (quiet, dispbuf);
521                 /* fill SDRAM */
522                 rdatapat = 0x12345678;
523                 sprintf (dispbuf, "writing block:     ");
524                 testm_puts (quiet, dispbuf);
525                 for (i = 0; i < size; i += blocksize) {
526                         sprintf (dispbuf, "%04lX\b\b\b\b", i / blocksize);
527                         testm_puts (quiet, dispbuf);
528                         test_stage[stage].test_write (startaddr + i, blocksize,
529                                                                                   &rdatapat);
530                 }                                               /* endfor */
531                 sprintf (dispbuf, "\n");
532                 testm_puts (quiet, dispbuf);
533                 if ((quiet & TEST_SHOW_PROG) == TEST_SHOW_PROG) {
534                         prog++;
535                         printf (".");
536                 }
537                 /* check SDRAM */
538                 rdatapat = 0x12345678;
539                 sprintf (dispbuf, "checking block:     ");
540                 testm_puts (quiet, dispbuf);
541                 for (i = 0; i < size; i += blocksize) {
542                         sprintf (dispbuf, "%04lX\b\b\b\b", i / blocksize);
543                         testm_puts (quiet, dispbuf);
544                         if ((perr =
545                                  test_stage[stage].test_check1 (quiet, startaddr + i,
546                                                                                                 blocksize,
547                                                                                                 &rdatapat)) != NULL) {
548                                 status = TEST_FAILED;
549                         }                                       /* endif */
550                 }                                               /* endfor */
551                 sprintf (dispbuf, "\n");
552                 testm_puts (quiet, dispbuf);
553                 if ((quiet & TEST_SHOW_PROG) == TEST_SHOW_PROG) {
554                         prog++;
555                         printf (".");
556                 }
557                 if (test_stage[stage].test_check2 != NULL) {
558                         /* check2 SDRAM */
559                         sprintf (dispbuf, "2nd checking block:     ");
560                         rdatapat = 0x12345678;
561                         testm_puts (quiet, dispbuf);
562                         for (i = 0; i < size; i += blocksize) {
563                                 sprintf (dispbuf, "%04lX\b\b\b\b", i / blocksize);
564                                 testm_puts (quiet, dispbuf);
565                                 if ((perr =
566                                          test_stage[stage].test_check2 (quiet, startaddr + i,
567                                                                                                         blocksize,
568                                                                                                         &rdatapat)) != NULL) {
569                                         status = TEST_FAILED;
570                                 }                               /* endif */
571                         }                                       /* endfor */
572                         sprintf (dispbuf, "\n");
573                         testm_puts (quiet, dispbuf);
574                         if ((quiet & TEST_SHOW_PROG) == TEST_SHOW_PROG) {
575                                 prog++;
576                                 printf (".");
577                         }
578                 }
579
580         }                                                       /* next stage */
581         if ((quiet & TEST_SHOW_PROG) == TEST_SHOW_PROG) {
582                 while (prog-- > 0)
583                         printf ("\b \b");
584         }
585
586         if (status == TEST_FAILED)
587                 errors++;
588
589         return (errors);
590 }