3 * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
5 * See file CREDITS for list of people who contributed to this
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.
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.
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,
26 add following code to PIP405.c :
32 i = getenv_r ("testmem", s, 32);
34 i = (int) simple_strtoul (s, NULL, 10);
35 if ((i > 0) && (i < 0xf)) {
37 i = mem_test (0, ramsize, i);
50 #include <asm/processor.h>
53 DECLARE_GLOBAL_DATA_PTR
;
59 #define TEST_SHOW_PROG 4
60 #define TEST_SHOW_ERR 2
61 #define TEST_SHOW_ALL 1
63 #define TESTPAT1 0xAA55AA55
64 #define TESTPAT2 0x55AA55AA
67 #define MEGABYTE (1024*1024)
71 volatile unsigned long pat1
;
72 volatile unsigned long pat2
;
73 } RAM_MEMTEST_PATTERN2
;
76 volatile unsigned long addr
;
77 } RAM_MEMTEST_ADDRLINE
;
79 static __inline
unsigned long Swap_32 (unsigned long val
)
81 return (((val
<< 16) & 0xFFFF0000) | ((val
>> 16) & 0x0000FFFF));
84 void testm_puts (int quiet
, char *buf
)
86 if ((quiet
& TEST_SHOW_ALL
) == TEST_SHOW_ALL
)
91 void Write_Error (int mode
, unsigned long addr
, unsigned long expected
,
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
);
105 * fills the memblock of <size> bytes from <startaddr> with pat1 and pat2
109 void RAM_MemTest_WritePattern2 (unsigned long startaddr
,
110 unsigned long size
, unsigned long pat1
,
113 RAM_MEMTEST_PATTERN2
*p
, *pe
;
115 p
= (RAM_MEMTEST_PATTERN2
*) startaddr
;
116 pe
= (RAM_MEMTEST_PATTERN2
*) (startaddr
+ size
);
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
130 void *RAM_MemTest_CheckPattern2 (int mode
, unsigned long startaddr
,
131 unsigned long size
, unsigned long pat1
,
134 RAM_MEMTEST_PATTERN2
*p
, *pe
;
135 unsigned long actual1
, actual2
;
137 p
= (RAM_MEMTEST_PATTERN2
*) startaddr
;
138 pe
= (RAM_MEMTEST_PATTERN2
*) (startaddr
+ size
);
144 if (actual1
!= pat1
) {
145 Write_Error (mode
, (unsigned long) &(p
->pat1
), pat1
, actual1
);
146 return ((void *) &(p
->pat1
));
149 if (actual2
!= pat2
) {
150 Write_Error (mode
, (unsigned long) &(p
->pat2
), pat2
, actual2
);
151 return ((void *) &(p
->pat2
));
161 * fills the memblock of <size> bytes from <startaddr> with the address
164 void RAM_MemTest_WriteAddrLine (unsigned long startaddr
,
165 unsigned long size
, int swapped
)
167 RAM_MEMTEST_ADDRLINE
*p
, *pe
;
169 p
= (RAM_MEMTEST_ADDRLINE
*) startaddr
;
170 pe
= (RAM_MEMTEST_ADDRLINE
*) (startaddr
+ size
);
174 p
->addr
= (unsigned long) p
;
179 p
->addr
= Swap_32 ((unsigned long) p
);
186 * checks the memblock of <size> bytes from <startaddr>
187 * returns the address of the error or NULL if all is well
190 void *RAM_MemTest_CheckAddrLine (int mode
, unsigned long startaddr
,
191 unsigned long size
, int swapped
)
193 RAM_MEMTEST_ADDRLINE
*p
, *pe
;
194 unsigned long actual
, expected
;
196 p
= (RAM_MEMTEST_ADDRLINE
*) startaddr
;
197 pe
= (RAM_MEMTEST_ADDRLINE
*) (startaddr
+ size
);
202 expected
= (unsigned long) p
;
203 if (actual
!= expected
) {
204 Write_Error (mode
, (unsigned long) &(p
->addr
), expected
,
206 return ((void *) &(p
->addr
));
213 expected
= Swap_32 ((unsigned long) p
);
214 if (actual
!= expected
) {
215 Write_Error (mode
, (unsigned long) &(p
->addr
), expected
,
217 return ((void *) &(p
->addr
));
227 * checks the memblock of <size> bytes from <startaddr+size>
228 * returns the address of the error or NULL if all is well
231 void *RAM_MemTest_CheckAddrLineReverse (int mode
, unsigned long startaddr
,
232 unsigned long size
, int swapped
)
234 RAM_MEMTEST_ADDRLINE
*p
, *pe
;
235 unsigned long actual
, expected
;
237 p
= (RAM_MEMTEST_ADDRLINE
*) (startaddr
+ size
- sizeof (p
->addr
));
238 pe
= (RAM_MEMTEST_ADDRLINE
*) startaddr
;
243 expected
= (unsigned long) p
;
244 if (actual
!= expected
) {
245 Write_Error (mode
, (unsigned long) &(p
->addr
), expected
,
247 return ((void *) &(p
->addr
));
254 expected
= Swap_32 ((unsigned long) p
);
255 if (actual
!= expected
) {
256 Write_Error (mode
, (unsigned long) &(p
->addr
), expected
,
258 return ((void *) &(p
->addr
));
268 * fills the memblock of <size> bytes from <startaddr> with walking bit pattern
271 void RAM_MemTest_WriteWalkBit (unsigned long startaddr
, unsigned long size
)
273 volatile unsigned long *p
, *pe
;
276 p
= (unsigned long *) startaddr
;
277 pe
= (unsigned long *) (startaddr
+ size
);
282 i
= (i
+ 1 + (((unsigned long) p
) >> 7)) % 32;
288 * checks the memblock of <size> bytes from <startaddr>
289 * returns the address of the error or NULL if all is well
292 void *RAM_MemTest_CheckWalkBit (int mode
, unsigned long startaddr
,
295 volatile unsigned long *p
, *pe
;
296 unsigned long actual
, expected
;
299 p
= (unsigned long *) startaddr
;
300 pe
= (unsigned long *) (startaddr
+ size
);
305 expected
= (1UL << i
);
306 if (actual
!= expected
) {
307 Write_Error (mode
, (unsigned long) p
, expected
, actual
);
310 i
= (i
+ 1 + (((unsigned long) p
) >> 7)) % 32;
318 * fills the memblock of <size> bytes from <startaddr> with "random" pattern
321 void RAM_MemTest_WriteRandomPattern (unsigned long startaddr
,
329 for (i
= 0; i
< (size
/ 4); i
++) {
330 *(unsigned long *) (startaddr
+ i
* 4) = p
;
344 * checks the memblock of <size> bytes from <startaddr>
345 * returns the address of the error or NULL if all is well
348 void *RAM_MemTest_CheckRandomPattern (int mode
, unsigned long startaddr
,
353 unsigned long i
, p
, p1
;
357 for (i
= 0; i
< (size
/ 4); i
++) {
358 p1
= *(unsigned long *) (startaddr
+ i
* 4);
361 Write_Error (mode
, startaddr
+ i
* 4, p
, p1
);
362 perr
= (void *) (startaddr
+ i
* 4);
381 void RAM_MemTest_WriteData1 (unsigned long startaddr
, unsigned long size
,
384 RAM_MemTest_WritePattern2 (startaddr
, size
, TESTPAT1
, TESTPAT2
);
387 void *RAM_MemTest_CheckData1 (int mode
, unsigned long startaddr
,
388 unsigned long size
, unsigned long *pat
)
390 return (RAM_MemTest_CheckPattern2
391 (mode
, startaddr
, size
, TESTPAT1
, TESTPAT2
));
394 void RAM_MemTest_WriteData2 (unsigned long startaddr
, unsigned long size
,
397 RAM_MemTest_WritePattern2 (startaddr
, size
, TESTPAT2
, TESTPAT1
);
400 void *RAM_MemTest_CheckData2 (int mode
, unsigned long startaddr
,
401 unsigned long size
, unsigned long *pat
)
403 return (RAM_MemTest_CheckPattern2
404 (mode
, startaddr
, size
, TESTPAT2
, TESTPAT1
));
407 void RAM_MemTest_WriteAddr1 (unsigned long startaddr
, unsigned long size
,
410 RAM_MemTest_WriteAddrLine (startaddr
, size
, FALSE
);
413 void *RAM_MemTest_Check1Addr1 (int mode
, unsigned long startaddr
,
414 unsigned long size
, unsigned long *pat
)
416 return (RAM_MemTest_CheckAddrLine (mode
, startaddr
, size
, FALSE
));
419 void *RAM_MemTest_Check2Addr1 (int mode
, unsigned long startaddr
,
420 unsigned long size
, unsigned long *pat
)
422 return (RAM_MemTest_CheckAddrLineReverse
423 (mode
, startaddr
, size
, FALSE
));
426 void RAM_MemTest_WriteAddr2 (unsigned long startaddr
, unsigned long size
,
429 RAM_MemTest_WriteAddrLine (startaddr
, size
, TRUE
);
432 void *RAM_MemTest_Check1Addr2 (int mode
, unsigned long startaddr
,
433 unsigned long size
, unsigned long *pat
)
435 return (RAM_MemTest_CheckAddrLine (mode
, startaddr
, size
, TRUE
));
438 void *RAM_MemTest_Check2Addr2 (int mode
, unsigned long startaddr
,
439 unsigned long size
, unsigned long *pat
)
441 return (RAM_MemTest_CheckAddrLineReverse
442 (mode
, startaddr
, size
, TRUE
));
447 void (*test_write
) (unsigned long startaddr
, unsigned long size
,
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
);
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
,
461 {RAM_MemTest_WriteData2
, "data test 2...\n", RAM_MemTest_CheckData2
,
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
}
471 void mem_test_reloc(void)
475 for (i
=0; i
< TEST_STAGES
; i
++) {
476 addr
= (ulong
) (test_stage
[i
].test_write
) + gd
->reloc_off
;
477 test_stage
[i
].test_write
=
478 (void (*) (unsigned long startaddr
, unsigned long size
,
479 unsigned long *pat
))addr
;
480 addr
= (ulong
) (test_stage
[i
].test_write_desc
) + gd
->reloc_off
;
481 test_stage
[i
].test_write_desc
=(char *)addr
;
482 if(test_stage
[i
].test_check1
) {
483 addr
= (ulong
) (test_stage
[i
].test_check1
) + gd
->reloc_off
;
484 test_stage
[i
].test_check1
=
485 (void *(*) (int mode
, unsigned long startaddr
,
486 unsigned long size
, unsigned long *pat
))addr
;
488 if(test_stage
[i
].test_check2
) {
489 addr
= (ulong
) (test_stage
[i
].test_check2
) + gd
->reloc_off
;
490 test_stage
[i
].test_check2
=
491 (void *(*) (int mode
, unsigned long startaddr
,
492 unsigned long size
, unsigned long *pat
))addr
;
498 int mem_test (unsigned long start
, unsigned long ramsize
, int quiet
)
500 unsigned long errors
, stage
;
501 unsigned long startaddr
, size
, i
;
502 const unsigned long blocksize
= 0x80000; /* check in 512KB blocks */
504 unsigned long rdatapat
;
506 int status
= TEST_PASSED
;
512 if ((quiet
& TEST_SHOW_PROG
) == TEST_SHOW_PROG
) {
516 sprintf (dispbuf
, "\nMemory Test: addr = 0x%lx size = 0x%lx\n",
518 testm_puts (quiet
, dispbuf
);
519 for (stage
= 0; stage
< TEST_STAGES
; stage
++) {
520 sprintf (dispbuf
, test_stage
[stage
].test_write_desc
);
521 testm_puts (quiet
, dispbuf
);
523 rdatapat
= 0x12345678;
524 sprintf (dispbuf
, "writing block: ");
525 testm_puts (quiet
, dispbuf
);
526 for (i
= 0; i
< size
; i
+= blocksize
) {
527 sprintf (dispbuf
, "%04lX\b\b\b\b", i
/ blocksize
);
528 testm_puts (quiet
, dispbuf
);
529 test_stage
[stage
].test_write (startaddr
+ i
, blocksize
,
532 sprintf (dispbuf
, "\n");
533 testm_puts (quiet
, dispbuf
);
534 if ((quiet
& TEST_SHOW_PROG
) == TEST_SHOW_PROG
) {
539 rdatapat
= 0x12345678;
540 sprintf (dispbuf
, "checking block: ");
541 testm_puts (quiet
, dispbuf
);
542 for (i
= 0; i
< size
; i
+= blocksize
) {
543 sprintf (dispbuf
, "%04lX\b\b\b\b", i
/ blocksize
);
544 testm_puts (quiet
, dispbuf
);
546 test_stage
[stage
].test_check1 (quiet
, startaddr
+ i
,
548 &rdatapat
)) != NULL
) {
549 status
= TEST_FAILED
;
552 sprintf (dispbuf
, "\n");
553 testm_puts (quiet
, dispbuf
);
554 if ((quiet
& TEST_SHOW_PROG
) == TEST_SHOW_PROG
) {
558 if (test_stage
[stage
].test_check2
!= NULL
) {
560 sprintf (dispbuf
, "2nd checking block: ");
561 rdatapat
= 0x12345678;
562 testm_puts (quiet
, dispbuf
);
563 for (i
= 0; i
< size
; i
+= blocksize
) {
564 sprintf (dispbuf
, "%04lX\b\b\b\b", i
/ blocksize
);
565 testm_puts (quiet
, dispbuf
);
567 test_stage
[stage
].test_check2 (quiet
, startaddr
+ i
,
569 &rdatapat
)) != NULL
) {
570 status
= TEST_FAILED
;
573 sprintf (dispbuf
, "\n");
574 testm_puts (quiet
, dispbuf
);
575 if ((quiet
& TEST_SHOW_PROG
) == TEST_SHOW_PROG
) {
582 if ((quiet
& TEST_SHOW_PROG
) == TEST_SHOW_PROG
) {
587 if (status
== TEST_FAILED
)