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