]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/hal/arm/xscale/iq80321/v2_0/src/diag/memtest.c
Initial revision
[karo-tx-redboot.git] / packages / hal / arm / xscale / iq80321 / v2_0 / src / diag / memtest.c
1 //=============================================================================
2 //
3 //      memtest.c
4 //
5 //=============================================================================
6 //####ECOSGPLCOPYRIGHTBEGIN####
7 // -------------------------------------------
8 // This file is part of eCos, the Embedded Configurable Operating System.
9 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
10 //
11 // eCos is free software; you can redistribute it and/or modify it under
12 // the terms of the GNU General Public License as published by the Free
13 // Software Foundation; either version 2 or (at your option) any later version.
14 //
15 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
16 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18 // for more details.
19 //
20 // You should have received a copy of the GNU General Public License along
21 // with eCos; if not, write to the Free Software Foundation, Inc.,
22 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 //
24 // As a special exception, if other files instantiate templates or use macros
25 // or inline functions from this file, or you compile this file and link it
26 // with other works to produce a work based on this file, this file does not
27 // by itself cause the resulting work to be covered by the GNU General Public
28 // License. However the source code for this file must still be made available
29 // in accordance with section (3) of the GNU General Public License.
30 //
31 // This exception does not invalidate any other reasons why a work based on
32 // this file might be covered by the GNU General Public License.
33 //
34 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
35 // at http://sources.redhat.com/ecos/ecos-license/
36 // -------------------------------------------
37 //####ECOSGPLCOPYRIGHTEND####
38 //=============================================================================
39 //#####DESCRIPTIONBEGIN####
40 //
41 // Author(s):   Scott Coulter, Jeff Frazier, Eric Breeden
42 // Contributors: Mark Salter
43 // Date:        2001-01-25
44 // Purpose:     
45 // Description: 
46 //
47 //####DESCRIPTIONEND####
48 //
49 //===========================================================================*/
50
51 /*************************************************************************
52 * Memtest.c - this file performs an address/address bar memory test.
53 *
54 *  Modification History
55 *  --------------------
56 *  01sep00 ejb Ported to StrongARM2
57 *  18dec00 snc
58 *  02feb01 jwf for snc
59 *  25jan02 Rewritten for RedBoot by Mark Salter
60 */
61
62 #include <redboot.h>
63
64 #define FAILED          1
65 #define PASSED          0
66
67 // Do walking one's test
68 //
69 static int
70 onesTest(CYG_ADDRWORD *testAddr)
71 {
72     CYG_ADDRWORD theOne, dataRead;
73     int fail, loopCount = 0; // To keep track of when to print CR
74
75     diag_printf("\n");
76
77     // Loop for all bits in an address
78     for (theOne = 1, fail = 0; theOne && !fail; theOne <<= 1) {
79
80         testAddr[0] = theOne;     // Write test data
81         testAddr[1] = ~0L;        // Drive d0-dn hi
82         dataRead = *testAddr;     // Read back data
83
84         diag_printf("%08x%s", dataRead, (++loopCount % 8) ? "" : "\n");
85
86         if (dataRead != theOne)  // Verify data
87             return FAILED;       // Signal failure
88     }
89     return PASSED;
90 }
91
92
93 // Do 32-bit word address test
94 //
95 static int
96 Addr32 (cyg_uint32 *start, cyg_uint32 *end, CYG_ADDRWORD *badAddr)
97 {
98     cyg_uint32 *currentAddr; /* Current address being tested */
99     cyg_uint32 data;
100
101     for(currentAddr = start; currentAddr <= end; currentAddr++)
102         *currentAddr = (cyg_uint32)(CYG_ADDRWORD)currentAddr;
103
104     for (currentAddr = start; currentAddr <= end; currentAddr++) {
105         data = *currentAddr;
106         if (data != (cyg_uint32)(CYG_ADDRWORD)currentAddr) {
107             diag_printf ("\n\nBad Read, Address = %p, Data Read = 0x%08x\n\n",
108                          currentAddr, data);
109             *badAddr = (CYG_ADDRWORD)currentAddr;
110             return FAILED;
111         }
112     }
113     return PASSED;
114 }
115
116
117 // Do inverse long word address test
118 //
119 static int
120 Bar32 (cyg_uint32 *start, cyg_uint32 *end, CYG_ADDRWORD *badAddr)
121 {
122     cyg_uint32 *currentAddr, data;
123
124     for(currentAddr = start; currentAddr <= end; currentAddr++)
125         *currentAddr = ~(CYG_ADDRWORD)currentAddr;
126
127     for (currentAddr = start; currentAddr <= end; currentAddr++) {
128         data = *currentAddr;
129         if (data != (~(CYG_ADDRWORD)currentAddr) & 0xffffffff) {
130             diag_printf ("\n\nBad Read, Address = %p, Data Read = 0x%08x\n\n",
131                          currentAddr, data);
132             *badAddr = (CYG_ADDRWORD)currentAddr;
133             return FAILED;
134         }
135     }
136     return PASSED;
137 }
138
139 // Do byte address test
140 //
141 static int
142 Addr8 (cyg_uint8 *start, cyg_uint8 *end, CYG_ADDRWORD *badAddr)
143 {
144     cyg_uint8 *currentAddr; // Current address being tested
145
146     for (currentAddr = start; currentAddr <= end; currentAddr++)
147         *currentAddr = (cyg_uint8)(CYG_ADDRWORD)currentAddr;
148
149     for (currentAddr = start; currentAddr <= end; currentAddr++)
150         if (*currentAddr != (cyg_uint8)(CYG_ADDRWORD)currentAddr) {
151             *badAddr = (CYG_ADDRWORD)currentAddr;
152             return FAILED;
153         }
154     return PASSED;
155 }
156
157 // Do inverse byte address test
158 //
159 static int
160 Bar8 (cyg_uint8 *start, cyg_uint8 *end, CYG_ADDRWORD *badAddr)
161 {
162     cyg_uint8 *currentAddr;  // Current address being tested
163
164     for(currentAddr = start; currentAddr <= end; currentAddr++)
165         *currentAddr = ~(CYG_ADDRWORD)currentAddr;
166
167     for(currentAddr = start; currentAddr <= end; currentAddr++)
168         if (*currentAddr != (~(CYG_ADDRWORD)currentAddr & 0xff)) {
169             *badAddr = (CYG_ADDRWORD)currentAddr;
170             return FAILED;
171         }
172     return PASSED;
173 }
174
175 // This routine is called if one of the memory tests fails.  It dumps
176 // the 8 32-bit words before and the 8 after the failure address
177 //
178 void
179 dumpMem (CYG_ADDRWORD badAddr)
180 {
181     cyg_uint32 *addr;
182     cyg_uint16 *saddr;
183     int i;
184
185     // Print out first line of mem dump
186     diag_printf("\n%p: %08x %08x %08x %08x",
187                 (char *)badAddr - 32,
188                 *(cyg_uint32 *)(badAddr - 32),
189                 *(cyg_uint32 *)(badAddr - 28),
190                 *(cyg_uint32 *)(badAddr - 24),
191                 *(cyg_uint32 *)(badAddr - 20));
192
193     diag_printf("\n%p: %08x %08x %08x %08x",
194                 (char *)badAddr - 16,
195                 *(cyg_uint32 *)(badAddr - 16),
196                 *(cyg_uint32 *)(badAddr - 12),
197                 *(cyg_uint32 *)(badAddr - 8),
198                 *(cyg_uint32 *)(badAddr - 4));
199
200     // Print out contents of fault addr
201     diag_printf("\n%p: %08x",
202                 (char *)badAddr, *(cyg_uint32 *)badAddr);
203
204     diag_printf("\n%p: %08x %08x %08x %08x",
205                 (char *)badAddr + 4,
206                 *(cyg_uint32 *)(badAddr + 4),
207                 *(cyg_uint32 *)(badAddr + 8),
208                 *(cyg_uint32 *)(badAddr + 12),
209                 *(cyg_uint32 *)(badAddr + 16));
210
211     diag_printf("\n%p: %08x %08x %08x %08x",
212                 (char *)badAddr + 20,
213                 *(cyg_uint32 *)(badAddr + 20),
214                 *(cyg_uint32 *)(badAddr + 24),
215                 *(cyg_uint32 *)(badAddr + 28),
216                 *(cyg_uint32 *)(badAddr + 32));
217
218     /* DEBUG */
219     diag_printf ("\n\nReading back data in 32bit chunks:\n");
220     for (addr = (cyg_uint32 *)(badAddr - 16), i = 0; i <= 8; i++, addr++)
221         diag_printf ("Address = %p, Data = 0x%08x\n", addr, *addr);
222     diag_printf ("\n");
223
224     diag_printf ("Reading back data in 16bit chunks:\n");
225     for (saddr = (cyg_uint16 *)(badAddr - 16), i = 0; i <= 16; i++, saddr++)
226         diag_printf ("Address = %p, Data = 0x%08x\n", saddr, *saddr);
227     diag_printf ("\n");
228 }
229
230 // Returns 1 if passed, 0 if failed.
231 //
232 int
233 memTest (CYG_ADDRWORD startAddr, CYG_ADDRWORD endAddr)
234 {
235     CYG_ADDRWORD badAddr;  // Addr test failed at
236
237     diag_printf("\nWalking 1's test: ");
238     if (onesTest((CYG_ADDRWORD *)startAddr) == FAILED)
239         goto failed;
240     diag_printf("passed");
241
242     diag_printf("\n32-bit address test: ");
243     if (Addr32((cyg_uint32 *)startAddr, (cyg_uint32 *)endAddr, &badAddr) == FAILED)
244         goto failed;
245     diag_printf("passed");
246
247     diag_printf("\n32-bit address bar test: ");
248     if (Bar32((cyg_uint32 *)startAddr, (cyg_uint32 *)endAddr, &badAddr) == FAILED)
249         goto failed;
250     diag_printf("passed");
251
252     diag_printf("\n8-bit address test: ");
253     if (Addr8((cyg_uint8 *)startAddr, (cyg_uint8 *)endAddr, &badAddr) == FAILED)
254         goto failed;
255     diag_printf("passed");
256
257     diag_printf("\nByte address bar test: ");
258     if (Bar8((cyg_uint8 *)startAddr, (cyg_uint8 *)endAddr, &badAddr) == FAILED)
259         goto failed;
260     diag_printf("passed");
261
262     return 1;
263
264  failed:
265     diag_printf("failed");
266     dumpMem(badAddr);
267     return 0;
268 }
269
270
271 /* 02/02/01 jwf */
272 /* Do alternating inverse long word address test */
273 static int
274 ABar32(cyg_uint32 *start,               /* Starting address of test */
275        cyg_uint32 *end,         /* Ending address */
276        CYG_ADDRWORD *badAddr)           /* Failure address */
277 {
278     register cyg_uint32 *currentAddr;   /* Current address being tested */
279     int fail = 0;               /* Test hasn't failed yet */
280     cyg_uint32 data;
281
282     /* In this test, the contents of each longword address toggles 
283        between the Address and the Address BAR */
284     for(currentAddr = start; currentAddr <= end; currentAddr++) {
285         
286         if ((CYG_ADDRWORD)currentAddr & 4) /* Address ending in 0x4 or 0xc */
287             *currentAddr = ~(cyg_uint32)(CYG_ADDRWORD)currentAddr;
288
289         else /* Address ending in 0x0 or 0x8 */ 
290             *currentAddr = (cyg_uint32)(CYG_ADDRWORD)currentAddr;
291     }
292
293     for (currentAddr = start; currentAddr <= end && !fail; currentAddr++) {
294         data = *currentAddr;
295
296         switch ((CYG_ADDRWORD)currentAddr & 0xf) {
297           case 0x0:
298           case 0x8:
299             if (data != (cyg_uint32)(CYG_ADDRWORD)currentAddr) {
300                 fail = 1;
301                 diag_printf ("\nFailed at Address %p, Expected 0x%08X, Read 0x%08X\n",
302                              currentAddr, (cyg_uint32)(CYG_ADDRWORD)currentAddr, data);
303             }
304             break;
305
306           case 0x4:
307           case 0xc:
308             if (data != ~(cyg_uint32)(CYG_ADDRWORD)currentAddr) {
309                 fail = 1;
310                 diag_printf ("\nFailed at Address %p, Expected 0x%08X, Read 0x%08X\n",
311                              currentAddr, ~(cyg_uint32)(CYG_ADDRWORD)currentAddr, data);
312             }
313             break;
314
315           default:
316             fail = 1;
317             diag_printf ("\nFailed at Address %p, Unaligned address\n", currentAddr);
318             break;
319         }
320     }
321
322     if (fail) {
323         *badAddr = (CYG_ADDRWORD)(--currentAddr);
324         return FAILED;
325     } else
326         return PASSED;
327 }
328
329
330 /* 02/02/01 jwf */
331 /*
332  * Returns 1 if passed, 0 if failed.
333  */
334 int
335 LoopMemTest (CYG_ADDRWORD startAddr, CYG_ADDRWORD endAddr)
336 {
337     CYG_ADDRWORD badAddr;  /* Addr test failed at */
338     volatile int junk;
339
340     while (1) {
341         diag_printf("\n");
342                         
343         diag_printf("\n32-bit address test: ");
344         if (Addr32((cyg_uint32 *)startAddr, (cyg_uint32 *)endAddr, &badAddr) == FAILED)
345             break;
346         diag_printf("passed");
347
348         diag_printf("\n32-bit address bar test: ");
349         if (Bar32((cyg_uint32 *)startAddr, (cyg_uint32 *)endAddr, &badAddr) == FAILED)
350             break;
351         diag_printf("passed");
352
353         diag_printf("\nAlternating Long word, Long word address bar test: ");
354         if (ABar32((cyg_uint32 *)startAddr, (cyg_uint32 *)endAddr, &badAddr) == FAILED)
355             break;
356         diag_printf("passed");
357     }
358
359     diag_printf("failed at Address %p\n", badAddr);
360     diag_printf("Performing Continuous Write/Read/!Write/Read...\n\n");
361     while (1) {
362         *(volatile int *)badAddr = badAddr;
363         junk = *(volatile int *)badAddr;
364         *(volatile int *)badAddr = ~badAddr;
365         junk = *(volatile int *)badAddr;
366     }
367
368     return 1;   // not reached
369 }
370
371