1*ad5bb451SWolfgang Denk /* 2*ad5bb451SWolfgang Denk * (C) Copyright 2002 3*ad5bb451SWolfgang Denk * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4*ad5bb451SWolfgang Denk * 5*ad5bb451SWolfgang Denk * See file CREDITS for list of people who contributed to this 6*ad5bb451SWolfgang Denk * project. 7*ad5bb451SWolfgang Denk * 8*ad5bb451SWolfgang Denk * This program is free software; you can redistribute it and/or 9*ad5bb451SWolfgang Denk * modify it under the terms of the GNU General Public License as 10*ad5bb451SWolfgang Denk * published by the Free Software Foundation; either version 2 of 11*ad5bb451SWolfgang Denk * the License, or (at your option) any later version. 12*ad5bb451SWolfgang Denk * 13*ad5bb451SWolfgang Denk * This program is distributed in the hope that it will be useful, 14*ad5bb451SWolfgang Denk * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*ad5bb451SWolfgang Denk * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*ad5bb451SWolfgang Denk * GNU General Public License for more details. 17*ad5bb451SWolfgang Denk * 18*ad5bb451SWolfgang Denk * You should have received a copy of the GNU General Public License 19*ad5bb451SWolfgang Denk * along with this program; if not, write to the Free Software 20*ad5bb451SWolfgang Denk * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21*ad5bb451SWolfgang Denk * MA 02111-1307 USA 22*ad5bb451SWolfgang Denk */ 23*ad5bb451SWolfgang Denk 24*ad5bb451SWolfgang Denk #include <common.h> 25*ad5bb451SWolfgang Denk 26*ad5bb451SWolfgang Denk /* Memory test 27*ad5bb451SWolfgang Denk * 28*ad5bb451SWolfgang Denk * General observations: 29*ad5bb451SWolfgang Denk * o The recommended test sequence is to test the data lines: if they are 30*ad5bb451SWolfgang Denk * broken, nothing else will work properly. Then test the address 31*ad5bb451SWolfgang Denk * lines. Finally, test the cells in the memory now that the test 32*ad5bb451SWolfgang Denk * program knows that the address and data lines work properly. 33*ad5bb451SWolfgang Denk * This sequence also helps isolate and identify what is faulty. 34*ad5bb451SWolfgang Denk * 35*ad5bb451SWolfgang Denk * o For the address line test, it is a good idea to use the base 36*ad5bb451SWolfgang Denk * address of the lowest memory location, which causes a '1' bit to 37*ad5bb451SWolfgang Denk * walk through a field of zeros on the address lines and the highest 38*ad5bb451SWolfgang Denk * memory location, which causes a '0' bit to walk through a field of 39*ad5bb451SWolfgang Denk * '1's on the address line. 40*ad5bb451SWolfgang Denk * 41*ad5bb451SWolfgang Denk * o Floating buses can fool memory tests if the test routine writes 42*ad5bb451SWolfgang Denk * a value and then reads it back immediately. The problem is, the 43*ad5bb451SWolfgang Denk * write will charge the residual capacitance on the data bus so the 44*ad5bb451SWolfgang Denk * bus retains its state briefely. When the test program reads the 45*ad5bb451SWolfgang Denk * value back immediately, the capacitance of the bus can allow it 46*ad5bb451SWolfgang Denk * to read back what was written, even though the memory circuitry 47*ad5bb451SWolfgang Denk * is broken. To avoid this, the test program should write a test 48*ad5bb451SWolfgang Denk * pattern to the target location, write a different pattern elsewhere 49*ad5bb451SWolfgang Denk * to charge the residual capacitance in a differnt manner, then read 50*ad5bb451SWolfgang Denk * the target location back. 51*ad5bb451SWolfgang Denk * 52*ad5bb451SWolfgang Denk * o Always read the target location EXACTLY ONCE and save it in a local 53*ad5bb451SWolfgang Denk * variable. The problem with reading the target location more than 54*ad5bb451SWolfgang Denk * once is that the second and subsequent reads may work properly, 55*ad5bb451SWolfgang Denk * resulting in a failed test that tells the poor technician that 56*ad5bb451SWolfgang Denk * "Memory error at 00000000, wrote aaaaaaaa, read aaaaaaaa" which 57*ad5bb451SWolfgang Denk * doesn't help him one bit and causes puzzled phone calls. Been there, 58*ad5bb451SWolfgang Denk * done that. 59*ad5bb451SWolfgang Denk * 60*ad5bb451SWolfgang Denk * Data line test: 61*ad5bb451SWolfgang Denk * --------------- 62*ad5bb451SWolfgang Denk * This tests data lines for shorts and opens by forcing adjacent data 63*ad5bb451SWolfgang Denk * to opposite states. Because the data lines could be routed in an 64*ad5bb451SWolfgang Denk * arbitrary manner the must ensure test patterns ensure that every case 65*ad5bb451SWolfgang Denk * is tested. By using the following series of binary patterns every 66*ad5bb451SWolfgang Denk * combination of adjacent bits is test regardless of routing. 67*ad5bb451SWolfgang Denk * 68*ad5bb451SWolfgang Denk * ...101010101010101010101010 69*ad5bb451SWolfgang Denk * ...110011001100110011001100 70*ad5bb451SWolfgang Denk * ...111100001111000011110000 71*ad5bb451SWolfgang Denk * ...111111110000000011111111 72*ad5bb451SWolfgang Denk * 73*ad5bb451SWolfgang Denk * Carrying this out, gives us six hex patterns as follows: 74*ad5bb451SWolfgang Denk * 75*ad5bb451SWolfgang Denk * 0xaaaaaaaaaaaaaaaa 76*ad5bb451SWolfgang Denk * 0xcccccccccccccccc 77*ad5bb451SWolfgang Denk * 0xf0f0f0f0f0f0f0f0 78*ad5bb451SWolfgang Denk * 0xff00ff00ff00ff00 79*ad5bb451SWolfgang Denk * 0xffff0000ffff0000 80*ad5bb451SWolfgang Denk * 0xffffffff00000000 81*ad5bb451SWolfgang Denk * 82*ad5bb451SWolfgang Denk * To test for short and opens to other signals on our boards, we 83*ad5bb451SWolfgang Denk * simply test with the 1's complemnt of the paterns as well, resulting 84*ad5bb451SWolfgang Denk * in twelve patterns total. 85*ad5bb451SWolfgang Denk * 86*ad5bb451SWolfgang Denk * After writing a test pattern. a special pattern 0x0123456789ABCDEF is 87*ad5bb451SWolfgang Denk * written to a different address in case the data lines are floating. 88*ad5bb451SWolfgang Denk * Thus, if a byte lane fails, you will see part of the special 89*ad5bb451SWolfgang Denk * pattern in that byte lane when the test runs. For example, if the 90*ad5bb451SWolfgang Denk * xx__xxxxxxxxxxxx byte line fails, you will see aa23aaaaaaaaaaaa 91*ad5bb451SWolfgang Denk * (for the 'a' test pattern). 92*ad5bb451SWolfgang Denk * 93*ad5bb451SWolfgang Denk * Address line test: 94*ad5bb451SWolfgang Denk * ------------------ 95*ad5bb451SWolfgang Denk * This function performs a test to verify that all the address lines 96*ad5bb451SWolfgang Denk * hooked up to the RAM work properly. If there is an address line 97*ad5bb451SWolfgang Denk * fault, it usually shows up as two different locations in the address 98*ad5bb451SWolfgang Denk * map (related by the faulty address line) mapping to one physical 99*ad5bb451SWolfgang Denk * memory storage location. The artifact that shows up is writing to 100*ad5bb451SWolfgang Denk * the first location "changes" the second location. 101*ad5bb451SWolfgang Denk * 102*ad5bb451SWolfgang Denk * To test all address lines, we start with the given base address and 103*ad5bb451SWolfgang Denk * xor the address with a '1' bit to flip one address line. For each 104*ad5bb451SWolfgang Denk * test, we shift the '1' bit left to test the next address line. 105*ad5bb451SWolfgang Denk * 106*ad5bb451SWolfgang Denk * In the actual code, we start with address sizeof(ulong) since our 107*ad5bb451SWolfgang Denk * test pattern we use is a ulong and thus, if we tried to test lower 108*ad5bb451SWolfgang Denk * order address bits, it wouldn't work because our pattern would 109*ad5bb451SWolfgang Denk * overwrite itself. 110*ad5bb451SWolfgang Denk * 111*ad5bb451SWolfgang Denk * Example for a 4 bit address space with the base at 0000: 112*ad5bb451SWolfgang Denk * 0000 <- base 113*ad5bb451SWolfgang Denk * 0001 <- test 1 114*ad5bb451SWolfgang Denk * 0010 <- test 2 115*ad5bb451SWolfgang Denk * 0100 <- test 3 116*ad5bb451SWolfgang Denk * 1000 <- test 4 117*ad5bb451SWolfgang Denk * Example for a 4 bit address space with the base at 0010: 118*ad5bb451SWolfgang Denk * 0010 <- base 119*ad5bb451SWolfgang Denk * 0011 <- test 1 120*ad5bb451SWolfgang Denk * 0000 <- (below the base address, skipped) 121*ad5bb451SWolfgang Denk * 0110 <- test 2 122*ad5bb451SWolfgang Denk * 1010 <- test 3 123*ad5bb451SWolfgang Denk * 124*ad5bb451SWolfgang Denk * The test locations are successively tested to make sure that they are 125*ad5bb451SWolfgang Denk * not "mirrored" onto the base address due to a faulty address line. 126*ad5bb451SWolfgang Denk * Note that the base and each test location are related by one address 127*ad5bb451SWolfgang Denk * line flipped. Note that the base address need not be all zeros. 128*ad5bb451SWolfgang Denk * 129*ad5bb451SWolfgang Denk * Memory tests 1-4: 130*ad5bb451SWolfgang Denk * ----------------- 131*ad5bb451SWolfgang Denk * These tests verify RAM using sequential writes and reads 132*ad5bb451SWolfgang Denk * to/from RAM. There are several test cases that use different patterns to 133*ad5bb451SWolfgang Denk * verify RAM. Each test case fills a region of RAM with one pattern and 134*ad5bb451SWolfgang Denk * then reads the region back and compares its contents with the pattern. 135*ad5bb451SWolfgang Denk * The following patterns are used: 136*ad5bb451SWolfgang Denk * 137*ad5bb451SWolfgang Denk * 1a) zero pattern (0x00000000) 138*ad5bb451SWolfgang Denk * 1b) negative pattern (0xffffffff) 139*ad5bb451SWolfgang Denk * 1c) checkerboard pattern (0x55555555) 140*ad5bb451SWolfgang Denk * 1d) checkerboard pattern (0xaaaaaaaa) 141*ad5bb451SWolfgang Denk * 2) bit-flip pattern ((1 << (offset % 32)) 142*ad5bb451SWolfgang Denk * 3) address pattern (offset) 143*ad5bb451SWolfgang Denk * 4) address pattern (~offset) 144*ad5bb451SWolfgang Denk * 145*ad5bb451SWolfgang Denk * Being run in normal mode, the test verifies only small 4Kb 146*ad5bb451SWolfgang Denk * regions of RAM around each 1Mb boundary. For example, for 64Mb 147*ad5bb451SWolfgang Denk * RAM the following areas are verified: 0x00000000-0x00000800, 148*ad5bb451SWolfgang Denk * 0x000ff800-0x00100800, 0x001ff800-0x00200800, ..., 0x03fff800- 149*ad5bb451SWolfgang Denk * 0x04000000. If the test is run in slow-test mode, it verifies 150*ad5bb451SWolfgang Denk * the whole RAM. 151*ad5bb451SWolfgang Denk */ 152*ad5bb451SWolfgang Denk 153*ad5bb451SWolfgang Denk #ifdef CONFIG_POST 154*ad5bb451SWolfgang Denk 155*ad5bb451SWolfgang Denk #include <post.h> 156*ad5bb451SWolfgang Denk #include <watchdog.h> 157*ad5bb451SWolfgang Denk 158*ad5bb451SWolfgang Denk #if CONFIG_POST & CFG_POST_MEMORY 159*ad5bb451SWolfgang Denk 160*ad5bb451SWolfgang Denk DECLARE_GLOBAL_DATA_PTR; 161*ad5bb451SWolfgang Denk 162*ad5bb451SWolfgang Denk /* 163*ad5bb451SWolfgang Denk * Define INJECT_*_ERRORS for testing error detection in the presence of 164*ad5bb451SWolfgang Denk * _good_ hardware. 165*ad5bb451SWolfgang Denk */ 166*ad5bb451SWolfgang Denk #undef INJECT_DATA_ERRORS 167*ad5bb451SWolfgang Denk #undef INJECT_ADDRESS_ERRORS 168*ad5bb451SWolfgang Denk 169*ad5bb451SWolfgang Denk #ifdef INJECT_DATA_ERRORS 170*ad5bb451SWolfgang Denk #warning "Injecting data line errors for testing purposes" 171*ad5bb451SWolfgang Denk #endif 172*ad5bb451SWolfgang Denk 173*ad5bb451SWolfgang Denk #ifdef INJECT_ADDRESS_ERRORS 174*ad5bb451SWolfgang Denk #warning "Injecting address line errors for testing purposes" 175*ad5bb451SWolfgang Denk #endif 176*ad5bb451SWolfgang Denk 177*ad5bb451SWolfgang Denk 178*ad5bb451SWolfgang Denk /* 179*ad5bb451SWolfgang Denk * This function performs a double word move from the data at 180*ad5bb451SWolfgang Denk * the source pointer to the location at the destination pointer. 181*ad5bb451SWolfgang Denk * This is helpful for testing memory on processors which have a 64 bit 182*ad5bb451SWolfgang Denk * wide data bus. 183*ad5bb451SWolfgang Denk * 184*ad5bb451SWolfgang Denk * On those PowerPC with FPU, use assembly and a floating point move: 185*ad5bb451SWolfgang Denk * this does a 64 bit move. 186*ad5bb451SWolfgang Denk * 187*ad5bb451SWolfgang Denk * For other processors, let the compiler generate the best code it can. 188*ad5bb451SWolfgang Denk */ 189*ad5bb451SWolfgang Denk static void move64(unsigned long long *src, unsigned long long *dest) 190*ad5bb451SWolfgang Denk { 191*ad5bb451SWolfgang Denk #if defined(CONFIG_MPC8260) || defined(CONFIG_MPC824X) 192*ad5bb451SWolfgang Denk asm ("lfd 0, 0(3)\n\t" /* fpr0 = *scr */ 193*ad5bb451SWolfgang Denk "stfd 0, 0(4)" /* *dest = fpr0 */ 194*ad5bb451SWolfgang Denk : : : "fr0" ); /* Clobbers fr0 */ 195*ad5bb451SWolfgang Denk return; 196*ad5bb451SWolfgang Denk #else 197*ad5bb451SWolfgang Denk *dest = *src; 198*ad5bb451SWolfgang Denk #endif 199*ad5bb451SWolfgang Denk } 200*ad5bb451SWolfgang Denk 201*ad5bb451SWolfgang Denk /* 202*ad5bb451SWolfgang Denk * This is 64 bit wide test patterns. Note that they reside in ROM 203*ad5bb451SWolfgang Denk * (which presumably works) and the tests write them to RAM which may 204*ad5bb451SWolfgang Denk * not work. 205*ad5bb451SWolfgang Denk * 206*ad5bb451SWolfgang Denk * The "otherpattern" is written to drive the data bus to values other 207*ad5bb451SWolfgang Denk * than the test pattern. This is for detecting floating bus lines. 208*ad5bb451SWolfgang Denk * 209*ad5bb451SWolfgang Denk */ 210*ad5bb451SWolfgang Denk const static unsigned long long pattern[] = { 211*ad5bb451SWolfgang Denk 0xaaaaaaaaaaaaaaaaULL, 212*ad5bb451SWolfgang Denk 0xccccccccccccccccULL, 213*ad5bb451SWolfgang Denk 0xf0f0f0f0f0f0f0f0ULL, 214*ad5bb451SWolfgang Denk 0xff00ff00ff00ff00ULL, 215*ad5bb451SWolfgang Denk 0xffff0000ffff0000ULL, 216*ad5bb451SWolfgang Denk 0xffffffff00000000ULL, 217*ad5bb451SWolfgang Denk 0x00000000ffffffffULL, 218*ad5bb451SWolfgang Denk 0x0000ffff0000ffffULL, 219*ad5bb451SWolfgang Denk 0x00ff00ff00ff00ffULL, 220*ad5bb451SWolfgang Denk 0x0f0f0f0f0f0f0f0fULL, 221*ad5bb451SWolfgang Denk 0x3333333333333333ULL, 222*ad5bb451SWolfgang Denk 0x5555555555555555ULL 223*ad5bb451SWolfgang Denk }; 224*ad5bb451SWolfgang Denk const unsigned long long otherpattern = 0x0123456789abcdefULL; 225*ad5bb451SWolfgang Denk 226*ad5bb451SWolfgang Denk 227*ad5bb451SWolfgang Denk static int memory_post_dataline(unsigned long long * pmem) 228*ad5bb451SWolfgang Denk { 229*ad5bb451SWolfgang Denk unsigned long long temp64 = 0; 230*ad5bb451SWolfgang Denk int num_patterns = sizeof(pattern)/ sizeof(pattern[0]); 231*ad5bb451SWolfgang Denk int i; 232*ad5bb451SWolfgang Denk unsigned int hi, lo, pathi, patlo; 233*ad5bb451SWolfgang Denk int ret = 0; 234*ad5bb451SWolfgang Denk 235*ad5bb451SWolfgang Denk for ( i = 0; i < num_patterns; i++) { 236*ad5bb451SWolfgang Denk move64((unsigned long long *)&(pattern[i]), pmem++); 237*ad5bb451SWolfgang Denk /* 238*ad5bb451SWolfgang Denk * Put a different pattern on the data lines: otherwise they 239*ad5bb451SWolfgang Denk * may float long enough to read back what we wrote. 240*ad5bb451SWolfgang Denk */ 241*ad5bb451SWolfgang Denk move64((unsigned long long *)&otherpattern, pmem--); 242*ad5bb451SWolfgang Denk move64(pmem, &temp64); 243*ad5bb451SWolfgang Denk 244*ad5bb451SWolfgang Denk #ifdef INJECT_DATA_ERRORS 245*ad5bb451SWolfgang Denk temp64 ^= 0x00008000; 246*ad5bb451SWolfgang Denk #endif 247*ad5bb451SWolfgang Denk 248*ad5bb451SWolfgang Denk if (temp64 != pattern[i]){ 249*ad5bb451SWolfgang Denk pathi = (pattern[i]>>32) & 0xffffffff; 250*ad5bb451SWolfgang Denk patlo = pattern[i] & 0xffffffff; 251*ad5bb451SWolfgang Denk 252*ad5bb451SWolfgang Denk hi = (temp64>>32) & 0xffffffff; 253*ad5bb451SWolfgang Denk lo = temp64 & 0xffffffff; 254*ad5bb451SWolfgang Denk 255*ad5bb451SWolfgang Denk post_log ("Memory (date line) error at %08x, " 256*ad5bb451SWolfgang Denk "wrote %08x%08x, read %08x%08x !\n", 257*ad5bb451SWolfgang Denk pmem, pathi, patlo, hi, lo); 258*ad5bb451SWolfgang Denk ret = -1; 259*ad5bb451SWolfgang Denk } 260*ad5bb451SWolfgang Denk } 261*ad5bb451SWolfgang Denk return ret; 262*ad5bb451SWolfgang Denk } 263*ad5bb451SWolfgang Denk 264*ad5bb451SWolfgang Denk static int memory_post_addrline(ulong *testaddr, ulong *base, ulong size) 265*ad5bb451SWolfgang Denk { 266*ad5bb451SWolfgang Denk ulong *target; 267*ad5bb451SWolfgang Denk ulong *end; 268*ad5bb451SWolfgang Denk ulong readback; 269*ad5bb451SWolfgang Denk ulong xor; 270*ad5bb451SWolfgang Denk int ret = 0; 271*ad5bb451SWolfgang Denk 272*ad5bb451SWolfgang Denk end = (ulong *)((ulong)base + size); /* pointer arith! */ 273*ad5bb451SWolfgang Denk xor = 0; 274*ad5bb451SWolfgang Denk for(xor = sizeof(ulong); xor > 0; xor <<= 1) { 275*ad5bb451SWolfgang Denk target = (ulong *)((ulong)testaddr ^ xor); 276*ad5bb451SWolfgang Denk if((target >= base) && (target < end)) { 277*ad5bb451SWolfgang Denk *testaddr = ~*target; 278*ad5bb451SWolfgang Denk readback = *target; 279*ad5bb451SWolfgang Denk 280*ad5bb451SWolfgang Denk #ifdef INJECT_ADDRESS_ERRORS 281*ad5bb451SWolfgang Denk if(xor == 0x00008000) { 282*ad5bb451SWolfgang Denk readback = *testaddr; 283*ad5bb451SWolfgang Denk } 284*ad5bb451SWolfgang Denk #endif 285*ad5bb451SWolfgang Denk if(readback == *testaddr) { 286*ad5bb451SWolfgang Denk post_log ("Memory (address line) error at %08x<->%08x, " 287*ad5bb451SWolfgang Denk "XOR value %08x !\n", 288*ad5bb451SWolfgang Denk testaddr, target, xor); 289*ad5bb451SWolfgang Denk ret = -1; 290*ad5bb451SWolfgang Denk } 291*ad5bb451SWolfgang Denk } 292*ad5bb451SWolfgang Denk } 293*ad5bb451SWolfgang Denk return ret; 294*ad5bb451SWolfgang Denk } 295*ad5bb451SWolfgang Denk 296*ad5bb451SWolfgang Denk static int memory_post_test1 (unsigned long start, 297*ad5bb451SWolfgang Denk unsigned long size, 298*ad5bb451SWolfgang Denk unsigned long val) 299*ad5bb451SWolfgang Denk { 300*ad5bb451SWolfgang Denk unsigned long i; 301*ad5bb451SWolfgang Denk ulong *mem = (ulong *) start; 302*ad5bb451SWolfgang Denk ulong readback; 303*ad5bb451SWolfgang Denk int ret = 0; 304*ad5bb451SWolfgang Denk 305*ad5bb451SWolfgang Denk for (i = 0; i < size / sizeof (ulong); i++) { 306*ad5bb451SWolfgang Denk mem[i] = val; 307*ad5bb451SWolfgang Denk if (i % 1024 == 0) 308*ad5bb451SWolfgang Denk WATCHDOG_RESET (); 309*ad5bb451SWolfgang Denk } 310*ad5bb451SWolfgang Denk 311*ad5bb451SWolfgang Denk for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) { 312*ad5bb451SWolfgang Denk readback = mem[i]; 313*ad5bb451SWolfgang Denk if (readback != val) { 314*ad5bb451SWolfgang Denk post_log ("Memory error at %08x, " 315*ad5bb451SWolfgang Denk "wrote %08x, read %08x !\n", 316*ad5bb451SWolfgang Denk mem + i, val, readback); 317*ad5bb451SWolfgang Denk 318*ad5bb451SWolfgang Denk ret = -1; 319*ad5bb451SWolfgang Denk break; 320*ad5bb451SWolfgang Denk } 321*ad5bb451SWolfgang Denk if (i % 1024 == 0) 322*ad5bb451SWolfgang Denk WATCHDOG_RESET (); 323*ad5bb451SWolfgang Denk } 324*ad5bb451SWolfgang Denk 325*ad5bb451SWolfgang Denk return ret; 326*ad5bb451SWolfgang Denk } 327*ad5bb451SWolfgang Denk 328*ad5bb451SWolfgang Denk static int memory_post_test2 (unsigned long start, unsigned long size) 329*ad5bb451SWolfgang Denk { 330*ad5bb451SWolfgang Denk unsigned long i; 331*ad5bb451SWolfgang Denk ulong *mem = (ulong *) start; 332*ad5bb451SWolfgang Denk ulong readback; 333*ad5bb451SWolfgang Denk int ret = 0; 334*ad5bb451SWolfgang Denk 335*ad5bb451SWolfgang Denk for (i = 0; i < size / sizeof (ulong); i++) { 336*ad5bb451SWolfgang Denk mem[i] = 1 << (i % 32); 337*ad5bb451SWolfgang Denk if (i % 1024 == 0) 338*ad5bb451SWolfgang Denk WATCHDOG_RESET (); 339*ad5bb451SWolfgang Denk } 340*ad5bb451SWolfgang Denk 341*ad5bb451SWolfgang Denk for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) { 342*ad5bb451SWolfgang Denk readback = mem[i]; 343*ad5bb451SWolfgang Denk if (readback != (1 << (i % 32))) { 344*ad5bb451SWolfgang Denk post_log ("Memory error at %08x, " 345*ad5bb451SWolfgang Denk "wrote %08x, read %08x !\n", 346*ad5bb451SWolfgang Denk mem + i, 1 << (i % 32), readback); 347*ad5bb451SWolfgang Denk 348*ad5bb451SWolfgang Denk ret = -1; 349*ad5bb451SWolfgang Denk break; 350*ad5bb451SWolfgang Denk } 351*ad5bb451SWolfgang Denk if (i % 1024 == 0) 352*ad5bb451SWolfgang Denk WATCHDOG_RESET (); 353*ad5bb451SWolfgang Denk } 354*ad5bb451SWolfgang Denk 355*ad5bb451SWolfgang Denk return ret; 356*ad5bb451SWolfgang Denk } 357*ad5bb451SWolfgang Denk 358*ad5bb451SWolfgang Denk static int memory_post_test3 (unsigned long start, unsigned long size) 359*ad5bb451SWolfgang Denk { 360*ad5bb451SWolfgang Denk unsigned long i; 361*ad5bb451SWolfgang Denk ulong *mem = (ulong *) start; 362*ad5bb451SWolfgang Denk ulong readback; 363*ad5bb451SWolfgang Denk int ret = 0; 364*ad5bb451SWolfgang Denk 365*ad5bb451SWolfgang Denk for (i = 0; i < size / sizeof (ulong); i++) { 366*ad5bb451SWolfgang Denk mem[i] = i; 367*ad5bb451SWolfgang Denk if (i % 1024 == 0) 368*ad5bb451SWolfgang Denk WATCHDOG_RESET (); 369*ad5bb451SWolfgang Denk } 370*ad5bb451SWolfgang Denk 371*ad5bb451SWolfgang Denk for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) { 372*ad5bb451SWolfgang Denk readback = mem[i]; 373*ad5bb451SWolfgang Denk if (readback != i) { 374*ad5bb451SWolfgang Denk post_log ("Memory error at %08x, " 375*ad5bb451SWolfgang Denk "wrote %08x, read %08x !\n", 376*ad5bb451SWolfgang Denk mem + i, i, readback); 377*ad5bb451SWolfgang Denk 378*ad5bb451SWolfgang Denk ret = -1; 379*ad5bb451SWolfgang Denk break; 380*ad5bb451SWolfgang Denk } 381*ad5bb451SWolfgang Denk if (i % 1024 == 0) 382*ad5bb451SWolfgang Denk WATCHDOG_RESET (); 383*ad5bb451SWolfgang Denk } 384*ad5bb451SWolfgang Denk 385*ad5bb451SWolfgang Denk return ret; 386*ad5bb451SWolfgang Denk } 387*ad5bb451SWolfgang Denk 388*ad5bb451SWolfgang Denk static int memory_post_test4 (unsigned long start, unsigned long size) 389*ad5bb451SWolfgang Denk { 390*ad5bb451SWolfgang Denk unsigned long i; 391*ad5bb451SWolfgang Denk ulong *mem = (ulong *) start; 392*ad5bb451SWolfgang Denk ulong readback; 393*ad5bb451SWolfgang Denk int ret = 0; 394*ad5bb451SWolfgang Denk 395*ad5bb451SWolfgang Denk for (i = 0; i < size / sizeof (ulong); i++) { 396*ad5bb451SWolfgang Denk mem[i] = ~i; 397*ad5bb451SWolfgang Denk if (i % 1024 == 0) 398*ad5bb451SWolfgang Denk WATCHDOG_RESET (); 399*ad5bb451SWolfgang Denk } 400*ad5bb451SWolfgang Denk 401*ad5bb451SWolfgang Denk for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) { 402*ad5bb451SWolfgang Denk readback = mem[i]; 403*ad5bb451SWolfgang Denk if (readback != ~i) { 404*ad5bb451SWolfgang Denk post_log ("Memory error at %08x, " 405*ad5bb451SWolfgang Denk "wrote %08x, read %08x !\n", 406*ad5bb451SWolfgang Denk mem + i, ~i, readback); 407*ad5bb451SWolfgang Denk 408*ad5bb451SWolfgang Denk ret = -1; 409*ad5bb451SWolfgang Denk break; 410*ad5bb451SWolfgang Denk } 411*ad5bb451SWolfgang Denk if (i % 1024 == 0) 412*ad5bb451SWolfgang Denk WATCHDOG_RESET (); 413*ad5bb451SWolfgang Denk } 414*ad5bb451SWolfgang Denk 415*ad5bb451SWolfgang Denk return ret; 416*ad5bb451SWolfgang Denk } 417*ad5bb451SWolfgang Denk 418*ad5bb451SWolfgang Denk static int memory_post_tests (unsigned long start, unsigned long size) 419*ad5bb451SWolfgang Denk { 420*ad5bb451SWolfgang Denk int ret = 0; 421*ad5bb451SWolfgang Denk 422*ad5bb451SWolfgang Denk if (ret == 0) 423*ad5bb451SWolfgang Denk ret = memory_post_dataline ((unsigned long long *)start); 424*ad5bb451SWolfgang Denk WATCHDOG_RESET (); 425*ad5bb451SWolfgang Denk if (ret == 0) 426*ad5bb451SWolfgang Denk ret = memory_post_addrline ((ulong *)start, (ulong *)start, size); 427*ad5bb451SWolfgang Denk WATCHDOG_RESET (); 428*ad5bb451SWolfgang Denk if (ret == 0) 429*ad5bb451SWolfgang Denk ret = memory_post_addrline ((ulong *)(start + size - 8), 430*ad5bb451SWolfgang Denk (ulong *)start, size); 431*ad5bb451SWolfgang Denk WATCHDOG_RESET (); 432*ad5bb451SWolfgang Denk if (ret == 0) 433*ad5bb451SWolfgang Denk ret = memory_post_test1 (start, size, 0x00000000); 434*ad5bb451SWolfgang Denk WATCHDOG_RESET (); 435*ad5bb451SWolfgang Denk if (ret == 0) 436*ad5bb451SWolfgang Denk ret = memory_post_test1 (start, size, 0xffffffff); 437*ad5bb451SWolfgang Denk WATCHDOG_RESET (); 438*ad5bb451SWolfgang Denk if (ret == 0) 439*ad5bb451SWolfgang Denk ret = memory_post_test1 (start, size, 0x55555555); 440*ad5bb451SWolfgang Denk WATCHDOG_RESET (); 441*ad5bb451SWolfgang Denk if (ret == 0) 442*ad5bb451SWolfgang Denk ret = memory_post_test1 (start, size, 0xaaaaaaaa); 443*ad5bb451SWolfgang Denk WATCHDOG_RESET (); 444*ad5bb451SWolfgang Denk if (ret == 0) 445*ad5bb451SWolfgang Denk ret = memory_post_test2 (start, size); 446*ad5bb451SWolfgang Denk WATCHDOG_RESET (); 447*ad5bb451SWolfgang Denk if (ret == 0) 448*ad5bb451SWolfgang Denk ret = memory_post_test3 (start, size); 449*ad5bb451SWolfgang Denk WATCHDOG_RESET (); 450*ad5bb451SWolfgang Denk if (ret == 0) 451*ad5bb451SWolfgang Denk ret = memory_post_test4 (start, size); 452*ad5bb451SWolfgang Denk WATCHDOG_RESET (); 453*ad5bb451SWolfgang Denk 454*ad5bb451SWolfgang Denk return ret; 455*ad5bb451SWolfgang Denk } 456*ad5bb451SWolfgang Denk 457*ad5bb451SWolfgang Denk int memory_post_test (int flags) 458*ad5bb451SWolfgang Denk { 459*ad5bb451SWolfgang Denk int ret = 0; 460*ad5bb451SWolfgang Denk bd_t *bd = gd->bd; 461*ad5bb451SWolfgang Denk unsigned long memsize = (bd->bi_memsize >= 256 << 20 ? 462*ad5bb451SWolfgang Denk 256 << 20 : bd->bi_memsize) - (1 << 20); 463*ad5bb451SWolfgang Denk 464*ad5bb451SWolfgang Denk 465*ad5bb451SWolfgang Denk if (flags & POST_SLOWTEST) { 466*ad5bb451SWolfgang Denk ret = memory_post_tests (CFG_SDRAM_BASE, memsize); 467*ad5bb451SWolfgang Denk } else { /* POST_NORMAL */ 468*ad5bb451SWolfgang Denk 469*ad5bb451SWolfgang Denk unsigned long i; 470*ad5bb451SWolfgang Denk 471*ad5bb451SWolfgang Denk for (i = 0; i < (memsize >> 20) && ret == 0; i++) { 472*ad5bb451SWolfgang Denk if (ret == 0) 473*ad5bb451SWolfgang Denk ret = memory_post_tests (i << 20, 0x800); 474*ad5bb451SWolfgang Denk if (ret == 0) 475*ad5bb451SWolfgang Denk ret = memory_post_tests ((i << 20) + 0xff800, 0x800); 476*ad5bb451SWolfgang Denk } 477*ad5bb451SWolfgang Denk } 478*ad5bb451SWolfgang Denk 479*ad5bb451SWolfgang Denk return ret; 480*ad5bb451SWolfgang Denk } 481*ad5bb451SWolfgang Denk 482*ad5bb451SWolfgang Denk #endif /* CONFIG_POST & CFG_POST_MEMORY */ 483*ad5bb451SWolfgang Denk #endif /* CONFIG_POST */ 484