X-Git-Url: http://git.ipfire.org/?p=people%2Fms%2Fu-boot.git;a=blobdiff_plain;f=post%2Fdrivers%2Fmemory.c;h=b410502873ad1753f2a739367e6aac158fdd73e8;hp=fbc349a852fba29e7484af7c664e1bd0ebd73a13;hb=b4f20767b12a5718ed8549aece73d405c6cac800;hpb=b90296fc39a33f84bb2b0aa79bf997be495ba791 diff --git a/post/drivers/memory.c b/post/drivers/memory.c index fbc349a852..b410502873 100644 --- a/post/drivers/memory.c +++ b/post/drivers/memory.c @@ -2,23 +2,7 @@ * (C) Copyright 2002 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -150,12 +134,10 @@ * the whole RAM. */ -#ifdef CONFIG_POST - #include #include -#if CONFIG_POST & CFG_POST_MEMORY +#if CONFIG_POST & (CONFIG_SYS_POST_MEMORY | CONFIG_SYS_POST_MEM_REGIONS) DECLARE_GLOBAL_DATA_PTR; @@ -186,16 +168,9 @@ DECLARE_GLOBAL_DATA_PTR; * * For other processors, let the compiler generate the best code it can. */ -static void move64(unsigned long long *src, unsigned long long *dest) +static void move64(const unsigned long long *src, unsigned long long *dest) { -#if defined(CONFIG_MPC8260) || defined(CONFIG_MPC824X) - asm ("lfd 0, 0(3)\n\t" /* fpr0 = *scr */ - "stfd 0, 0(4)" /* *dest = fpr0 */ - : : : "fr0" ); /* Clobbers fr0 */ - return; -#else *dest = *src; -#endif } /* @@ -227,18 +202,18 @@ const unsigned long long otherpattern = 0x0123456789abcdefULL; static int memory_post_dataline(unsigned long long * pmem) { unsigned long long temp64 = 0; - int num_patterns = sizeof(pattern)/ sizeof(pattern[0]); + int num_patterns = ARRAY_SIZE(pattern); int i; unsigned int hi, lo, pathi, patlo; int ret = 0; for ( i = 0; i < num_patterns; i++) { - move64((unsigned long long *)&(pattern[i]), pmem++); + move64(&(pattern[i]), pmem++); /* * Put a different pattern on the data lines: otherwise they * may float long enough to read back what we wrote. */ - move64((unsigned long long *)&otherpattern, pmem--); + move64(&otherpattern, pmem--); move64(pmem, &temp64); #ifdef INJECT_DATA_ERRORS @@ -252,7 +227,7 @@ static int memory_post_dataline(unsigned long long * pmem) hi = (temp64>>32) & 0xffffffff; lo = temp64 & 0xffffffff; - post_log ("Memory (date line) error at %08x, " + post_log("Memory (data line) error at %08x, " "wrote %08x%08x, read %08x%08x !\n", pmem, pathi, patlo, hi, lo); ret = -1; @@ -283,8 +258,8 @@ static int memory_post_addrline(ulong *testaddr, ulong *base, ulong size) } #endif if(readback == *testaddr) { - post_log ("Memory (address line) error at %08x<->%08x, " - "XOR value %08x !\n", + post_log("Memory (address line) error at %08x<->%08x, " + "XOR value %08x !\n", testaddr, target, xor); ret = -1; } @@ -293,7 +268,7 @@ static int memory_post_addrline(ulong *testaddr, ulong *base, ulong size) return ret; } -static int memory_post_test1 (unsigned long start, +static int memory_post_test1(unsigned long start, unsigned long size, unsigned long val) { @@ -305,13 +280,13 @@ static int memory_post_test1 (unsigned long start, for (i = 0; i < size / sizeof (ulong); i++) { mem[i] = val; if (i % 1024 == 0) - WATCHDOG_RESET (); + WATCHDOG_RESET(); } - for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) { + for (i = 0; i < size / sizeof (ulong) && !ret; i++) { readback = mem[i]; if (readback != val) { - post_log ("Memory error at %08x, " + post_log("Memory error at %08x, " "wrote %08x, read %08x !\n", mem + i, val, readback); @@ -319,13 +294,13 @@ static int memory_post_test1 (unsigned long start, break; } if (i % 1024 == 0) - WATCHDOG_RESET (); + WATCHDOG_RESET(); } return ret; } -static int memory_post_test2 (unsigned long start, unsigned long size) +static int memory_post_test2(unsigned long start, unsigned long size) { unsigned long i; ulong *mem = (ulong *) start; @@ -335,13 +310,13 @@ static int memory_post_test2 (unsigned long start, unsigned long size) for (i = 0; i < size / sizeof (ulong); i++) { mem[i] = 1 << (i % 32); if (i % 1024 == 0) - WATCHDOG_RESET (); + WATCHDOG_RESET(); } - for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) { + for (i = 0; i < size / sizeof (ulong) && !ret; i++) { readback = mem[i]; if (readback != (1 << (i % 32))) { - post_log ("Memory error at %08x, " + post_log("Memory error at %08x, " "wrote %08x, read %08x !\n", mem + i, 1 << (i % 32), readback); @@ -349,13 +324,13 @@ static int memory_post_test2 (unsigned long start, unsigned long size) break; } if (i % 1024 == 0) - WATCHDOG_RESET (); + WATCHDOG_RESET(); } return ret; } -static int memory_post_test3 (unsigned long start, unsigned long size) +static int memory_post_test3(unsigned long start, unsigned long size) { unsigned long i; ulong *mem = (ulong *) start; @@ -365,13 +340,13 @@ static int memory_post_test3 (unsigned long start, unsigned long size) for (i = 0; i < size / sizeof (ulong); i++) { mem[i] = i; if (i % 1024 == 0) - WATCHDOG_RESET (); + WATCHDOG_RESET(); } - for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) { + for (i = 0; i < size / sizeof (ulong) && !ret; i++) { readback = mem[i]; if (readback != i) { - post_log ("Memory error at %08x, " + post_log("Memory error at %08x, " "wrote %08x, read %08x !\n", mem + i, i, readback); @@ -379,13 +354,13 @@ static int memory_post_test3 (unsigned long start, unsigned long size) break; } if (i % 1024 == 0) - WATCHDOG_RESET (); + WATCHDOG_RESET(); } return ret; } -static int memory_post_test4 (unsigned long start, unsigned long size) +static int memory_post_test4(unsigned long start, unsigned long size) { unsigned long i; ulong *mem = (ulong *) start; @@ -395,13 +370,13 @@ static int memory_post_test4 (unsigned long start, unsigned long size) for (i = 0; i < size / sizeof (ulong); i++) { mem[i] = ~i; if (i % 1024 == 0) - WATCHDOG_RESET (); + WATCHDOG_RESET(); } - for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) { + for (i = 0; i < size / sizeof (ulong) && !ret; i++) { readback = mem[i]; if (readback != ~i) { - post_log ("Memory error at %08x, " + post_log("Memory error at %08x, " "wrote %08x, read %08x !\n", mem + i, ~i, readback); @@ -409,78 +384,160 @@ static int memory_post_test4 (unsigned long start, unsigned long size) break; } if (i % 1024 == 0) - WATCHDOG_RESET (); + WATCHDOG_RESET(); } return ret; } -static int memory_post_tests (unsigned long start, unsigned long size) +static int memory_post_test_lines(unsigned long start, unsigned long size) +{ + int ret = 0; + + ret = memory_post_dataline((unsigned long long *)start); + WATCHDOG_RESET(); + if (!ret) + ret = memory_post_addrline((ulong *)start, (ulong *)start, + size); + WATCHDOG_RESET(); + if (!ret) + ret = memory_post_addrline((ulong *)(start+size-8), + (ulong *)start, size); + WATCHDOG_RESET(); + + return ret; +} + +static int memory_post_test_patterns(unsigned long start, unsigned long size) { int ret = 0; - if (ret == 0) - ret = memory_post_dataline ((unsigned long long *)start); - WATCHDOG_RESET (); - if (ret == 0) - ret = memory_post_addrline ((ulong *)start, (ulong *)start, size); - WATCHDOG_RESET (); - if (ret == 0) - ret = memory_post_addrline ((ulong *)(start + size - 8), - (ulong *)start, size); - WATCHDOG_RESET (); - if (ret == 0) - ret = memory_post_test1 (start, size, 0x00000000); - WATCHDOG_RESET (); - if (ret == 0) - ret = memory_post_test1 (start, size, 0xffffffff); - WATCHDOG_RESET (); - if (ret == 0) - ret = memory_post_test1 (start, size, 0x55555555); - WATCHDOG_RESET (); - if (ret == 0) - ret = memory_post_test1 (start, size, 0xaaaaaaaa); - WATCHDOG_RESET (); - if (ret == 0) - ret = memory_post_test2 (start, size); - WATCHDOG_RESET (); - if (ret == 0) - ret = memory_post_test3 (start, size); - WATCHDOG_RESET (); - if (ret == 0) - ret = memory_post_test4 (start, size); - WATCHDOG_RESET (); + ret = memory_post_test1(start, size, 0x00000000); + WATCHDOG_RESET(); + if (!ret) + ret = memory_post_test1(start, size, 0xffffffff); + WATCHDOG_RESET(); + if (!ret) + ret = memory_post_test1(start, size, 0x55555555); + WATCHDOG_RESET(); + if (!ret) + ret = memory_post_test1(start, size, 0xaaaaaaaa); + WATCHDOG_RESET(); + if (!ret) + ret = memory_post_test2(start, size); + WATCHDOG_RESET(); + if (!ret) + ret = memory_post_test3(start, size); + WATCHDOG_RESET(); + if (!ret) + ret = memory_post_test4(start, size); + WATCHDOG_RESET(); return ret; } -int memory_post_test (int flags) +static int memory_post_test_regions(unsigned long start, unsigned long size) { + unsigned long i; int ret = 0; + + for (i = 0; i < (size >> 20) && (!ret); i++) { + if (!ret) + ret = memory_post_test_patterns(start + (i << 20), + 0x800); + if (!ret) + ret = memory_post_test_patterns(start + (i << 20) + + 0xff800, 0x800); + } + + return ret; +} + +static int memory_post_tests(unsigned long start, unsigned long size) +{ + int ret = 0; + + ret = memory_post_test_lines(start, size); + if (!ret) + ret = memory_post_test_patterns(start, size); + + return ret; +} + +/* + * !! this is only valid, if you have contiguous memory banks !! + */ +__attribute__((weak)) +int arch_memory_test_prepare(u32 *vstart, u32 *size, phys_addr_t *phys_offset) +{ bd_t *bd = gd->bd; - unsigned long memsize = (bd->bi_memsize >= 256 << 20 ? - 256 << 20 : bd->bi_memsize) - (1 << 20); + + *vstart = CONFIG_SYS_SDRAM_BASE; + *size = (gd->ram_size >= 256 << 20 ? + 256 << 20 : gd->ram_size) - (1 << 20); /* Limit area to be tested with the board info struct */ - if (CFG_SDRAM_BASE + memsize > (ulong)bd) - memsize = (ulong)bd - CFG_SDRAM_BASE; + if ((*vstart) + (*size) > (ulong)bd) + *size = (ulong)bd - *vstart; + + return 0; +} + +__attribute__((weak)) +int arch_memory_test_advance(u32 *vstart, u32 *size, phys_addr_t *phys_offset) +{ + return 1; +} + +__attribute__((weak)) +int arch_memory_test_cleanup(u32 *vstart, u32 *size, phys_addr_t *phys_offset) +{ + return 0; +} + +__attribute__((weak)) +void arch_memory_failure_handle(void) +{ + return; +} + +int memory_regions_post_test(int flags) +{ + int ret = 0; + phys_addr_t phys_offset = 0; + u32 memsize, vstart; - if (flags & POST_SLOWTEST) { - ret = memory_post_tests (CFG_SDRAM_BASE, memsize); - } else { /* POST_NORMAL */ + arch_memory_test_prepare(&vstart, &memsize, &phys_offset); - unsigned long i; + ret = memory_post_test_lines(vstart, memsize); + if (!ret) + ret = memory_post_test_regions(vstart, memsize); + + return ret; +} - for (i = 0; i < (memsize >> 20) && ret == 0; i++) { - if (ret == 0) - ret = memory_post_tests (i << 20, 0x800); - if (ret == 0) - ret = memory_post_tests ((i << 20) + 0xff800, 0x800); +int memory_post_test(int flags) +{ + int ret = 0; + phys_addr_t phys_offset = 0; + u32 memsize, vstart; + + arch_memory_test_prepare(&vstart, &memsize, &phys_offset); + + do { + if (flags & POST_SLOWTEST) { + ret = memory_post_tests(vstart, memsize); + } else { /* POST_NORMAL */ + ret = memory_post_test_regions(vstart, memsize); } - } + } while (!ret && + !arch_memory_test_advance(&vstart, &memsize, &phys_offset)); + + arch_memory_test_cleanup(&vstart, &memsize, &phys_offset); + if (ret) + arch_memory_failure_handle(); return ret; } -#endif /* CONFIG_POST & CFG_POST_MEMORY */ -#endif /* CONFIG_POST */ +#endif /* CONFIG_POST&(CONFIG_SYS_POST_MEMORY|CONFIG_SYS_POST_MEM_REGIONS) */