From e77b9a0ab79d930e76c8713bd6fb05c2e7dfbd9e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ky=C3=B6sti=20M=C3=A4lkki?= Date: Sat, 17 Mar 2012 08:09:14 +0100 Subject: [PATCH] Replace ramtest pattern to assist in DIMM configuration MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This is developer's testtool. Output from a "rotate ones" -style pattern helps figure out how DIMM addresses are encoded or routed on a certain mainboard. Scattered test should cover every data and address lines on the memory bus, but is probably limited to the first bank of first DIMM. Change-Id: I533a7a873bcc434f99e7faed9dc9337d9ab64196 Signed-off-by: Kyösti Mälkki Signed-off-by: Patrick Georgi [pg: rebase] Reviewed-on: http://review.coreboot.org/294 Tested-by: build bot (Jenkins) Reviewed-by: Rudolf Marek --- src/lib/ramtest.c | 185 +++++++++++++++++++++++----------------------- 1 file changed, 94 insertions(+), 91 deletions(-) diff --git a/src/lib/ramtest.c b/src/lib/ramtest.c index e118062c2..345721073 100644 --- a/src/lib/ramtest.c +++ b/src/lib/ramtest.c @@ -47,100 +47,114 @@ static void phys_memory_barrier(void) #endif } -static void ram_fill(unsigned long start, unsigned long stop) +/** + * Rotate ones test pattern that access every bit on a 128bit wide + * memory bus. To test most address lines, addresses are scattered + * using 256B, 4kB and 64kB increments. + * + * @idx Index to test pattern (0=> 8) + 1; + j = (idx >> 4) & 0x0f; + *addr = idx & 0x0f; + *addr |= j << (4*k); + *value = 0x01010101 << (j & 7); + if (j & 8) + *value = ~(*value); } -static int ram_verify_nodie(unsigned long start, unsigned long stop) +/** + * Simple write-read-verify memory test. See console debug output for + * any dislocated bytes. + * + * @start System memory offset, aligned to 128bytes + */ +static int ram_bitset_nodie(unsigned long start) { - unsigned long addr; - int i = 0; - /* - * Verify. - */ + unsigned long addr, value, value2; + unsigned short int idx; + unsigned char failed, failures; + uint8_t verbose = 0; + #if !defined(__ROMCC__) - printk(BIOS_DEBUG, "DRAM verify: 0x%08lx-0x%08lx\n", start, stop); + printk(BIOS_DEBUG, "DRAM bitset write: 0x%08lx\n", start); #else - print_debug("DRAM verify: "); + print_debug("DRAM bitset write: 0x"); print_debug_hex32(start); - print_debug_char('-'); - print_debug_hex32(stop); print_debug("\n"); #endif - for(addr = start; addr < stop ; addr += 4) { - unsigned long value; - /* Display address being tested */ - if (!(addr & 0xfffff)) { + for (idx=0; idx<0x400; idx+=4) { + test_pattern(idx, &addr, &value); + write_phys(start + addr, value); + } + + /* Make sure we don't read before we wrote */ + phys_memory_barrier(); + #if !defined(__ROMCC__) - printk(BIOS_DEBUG, "%08lx \r", addr); + printk(BIOS_DEBUG, "DRAM bitset verify: 0x%08lx\n", start); #else - print_debug_hex32(addr); - print_debug(" \r"); + print_debug("DRAM bitset verify: 0x"); + print_debug_hex32(start); + print_debug("\n"); #endif - } - value = read_phys(addr); - if (value != addr) { - /* Display address with error */ + failures = 0; + for (idx=0; idx<0x400; idx+=4) { + test_pattern(idx, &addr, &value); + value2 = read_phys(start + addr); + + failed = (value2 != value); + failures |= failed; + if (failed && !verbose) { #if !defined(__ROMCC__) - printk(BIOS_ERR, "Fail: @0x%08lx Read value=0x%08lx\n", addr, value); + printk(BIOS_ERR, "0x%08lx wr: 0x%08lx rd: 0x%08lx FAIL\n", + start + addr, value, value2); #else - print_err("Fail: @0x"); - print_err_hex32(addr); - print_err(" Read value=0x"); + print_err_hex32(start + addr); + print_err(" wr: 0x"); print_err_hex32(value); - print_err("\n"); + print_err(" rd: 0x"); + print_err_hex32(value2); + print_err(" FAIL\n"); #endif - i++; - if(i>256) { + } + if (verbose) { #if !defined(__ROMCC__) - printk(BIOS_DEBUG, "Aborting.\n"); -#else - print_debug("Aborting.\n"); -#endif - break; + if ((addr & 0x0f) == 0) + printk(BIOS_DEBUG, "%08lx wr: %08lx rd:", + start + addr, value); + if (failed) + printk(BIOS_DEBUG, " %08lx!", value2); + else + printk(BIOS_DEBUG, " %08lx ", value2); + if ((addr & 0x0f) == 0xc) + printk(BIOS_DEBUG, "\n"); +#else + if ((addr & 0x0f) == 0) { + print_dbg_hex32(start + addr); + print_dbg(" wr: "); + print_dbg_hex32(value); + print_dbg(" rd: "); } + print_dbg_hex32(value2); + if (failed) + print_dbg("! "); + else + print_dbg(" "); + if ((addr & 0x0f) == 0xc) + print_dbg("\n"); +#endif } } - /* Display final address */ -#if !defined(__ROMCC__) - printk(BIOS_DEBUG, "%08lx", addr); -#else - print_debug_hex32(addr); -#endif - - if (i) { + if (failures) { + post_code(0xea); #if !defined(__ROMCC__) printk(BIOS_DEBUG, "\nDRAM did _NOT_ verify!\n"); #else @@ -168,18 +182,13 @@ void ram_check(unsigned long start, unsigned long stop) * are tested. -Tyson */ #if !defined(__ROMCC__) - printk(BIOS_DEBUG, "Testing DRAM : %08lx - %08lx\n", start, stop); + printk(BIOS_DEBUG, "Testing DRAM at: %08lx\n", start); #else - print_debug("Testing DRAM : "); + print_debug("Testing DRAM at: "); print_debug_hex32(start); - print_debug("-"); - print_debug_hex32(stop); print_debug("\n"); #endif - ram_fill(start, stop); - /* Make sure we don't read before we wrote */ - phys_memory_barrier(); - if (ram_verify_nodie(start, stop)) + if (ram_bitset_nodie(start)) die("DRAM ERROR"); #if !defined(__ROMCC__) printk(BIOS_DEBUG, "Done.\n"); @@ -198,19 +207,14 @@ int ram_check_nodie(unsigned long start, unsigned long stop) * are tested. -Tyson */ #if !defined(__ROMCC__) - printk(BIOS_DEBUG, "Testing DRAM : %08lx - %08lx\n", start, stop); + printk(BIOS_DEBUG, "Testing DRAM at : %08lx\n", start); #else - print_debug("Testing DRAM : "); + print_debug("Testing DRAM at : "); print_debug_hex32(start); - print_debug("-"); - print_debug_hex32(stop); print_debug("\n"); #endif - ram_fill(start, stop); - /* Make sure we don't read before we wrote */ - phys_memory_barrier(); - ret = ram_verify_nodie(start, stop); + ret = ram_bitset_nodie(start); #if !defined(__ROMCC__) printk(BIOS_DEBUG, "Done.\n"); #else @@ -248,4 +252,3 @@ void quick_ram_check(void) } phys_memory_barrier(); } - -- 2.25.1