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