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