[U-Boot] [PATCH 2/7] Expand POST memory test to support arch-depended implementation.

York Sun yorksun at freescale.com
Fri Aug 27 23:25:51 CEST 2010


Add progress indicator for slow test. It is useful when the testing
takes too longer to finish. The indicator is reused from flash
programming.

Hwconfig is used to turn on slow test when not enabled by flag.

Signed-off-by: York Sun <yorksun at freescale.com>
---
 post/drivers/memory.c |  211 +++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 171 insertions(+), 40 deletions(-)

diff --git a/post/drivers/memory.c b/post/drivers/memory.c
index 0062360..4020fc2 100644
--- a/post/drivers/memory.c
+++ b/post/drivers/memory.c
@@ -22,7 +22,7 @@
  */
 
 #include <common.h>
-
+#include <hwconfig.h>
 /* Memory test
  *
  * General observations:
@@ -172,6 +172,21 @@ DECLARE_GLOBAL_DATA_PTR;
 #warning "Injecting address line errors for testing purposes"
 #endif
 
+#define TOTAL_PROGRESS_DOTS 45
+#define TOTAL_PROGRESS_NUMBERS 9
+#define PROGRESS_DOTS_PER_NUMBER (TOTAL_PROGRESS_DOTS/TOTAL_PROGRESS_NUMBERS)
+#define TEST_SHOW_PROGRESS(scale, dots, digit, dots_sub) \
+{ \
+	dots -= (dots_sub); \
+	if ((scale > 0) && (dots <= 0)) { \
+		if ((digit % PROGRESS_DOTS_PER_NUMBER) == 0) \
+			printf("%d", digit / PROGRESS_DOTS_PER_NUMBER); \
+		else \
+			putc('.'); \
+		digit--; \
+		dots += (scale); \
+	} \
+}
 
 /*
  * This function performs a double word move from the data at
@@ -291,21 +306,34 @@ 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)
+			      unsigned long val,
+			      int fast)
 {
 	unsigned long i;
 	ulong *mem = (ulong *) start;
 	ulong readback;
 	int ret = 0;
+	int digit, dots;
+	int scale;
+
+	scale = (int)(((size >> 22) + TOTAL_PROGRESS_DOTS - 1) /
+		TOTAL_PROGRESS_DOTS);
+	digit = TOTAL_PROGRESS_DOTS;
+	dots  = 0;
 
 	for (i = 0; i < size / sizeof (ulong); i++) {
 		mem[i] = val;
 		if (i % 1024 == 0)
 			WATCHDOG_RESET ();
+		if (!fast && (i & 0xFFFFF) == 0)
+			TEST_SHOW_PROGRESS(scale, dots, digit, 1);
 	}
-
+	if (!fast)
+		printf("Filled with 0x%lx\n", val);
+	digit = TOTAL_PROGRESS_DOTS;
+	dots  = 0;
 	for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
 		readback = mem[i];
 		if (readback != val) {
@@ -318,24 +346,45 @@ static int memory_post_test1 (unsigned long start,
 		}
 		if (i % 1024 == 0)
 			WATCHDOG_RESET ();
+		if (!fast && (i & 0xFFFFF) == 0)
+			TEST_SHOW_PROGRESS(scale, dots, digit, 1);
+	}
+	if (!fast) {
+		if (ret == 0)
+			puts("Verified OK.\n\n");
+		else
+			puts("\nFailed!\n\n");
 	}
-
 	return ret;
 }
 
-static int memory_post_test2 (unsigned long start, unsigned long size)
+static int memory_post_test2(unsigned long start, unsigned long size, int fast)
 {
 	unsigned long i;
 	ulong *mem = (ulong *) start;
 	ulong readback;
 	int ret = 0;
+	int digit, dots;
+	int scale;
+
+	scale = (int)(((size >> 22) + TOTAL_PROGRESS_DOTS - 1) /
+		TOTAL_PROGRESS_DOTS);
+	digit = TOTAL_PROGRESS_DOTS;
+	dots  = 0;
 
 	for (i = 0; i < size / sizeof (ulong); i++) {
 		mem[i] = 1 << (i % 32);
 		if (i % 1024 == 0)
 			WATCHDOG_RESET ();
+		if (!fast && (i & 0xFFFFF) == 0)
+			TEST_SHOW_PROGRESS(scale, dots, digit, 1);
 	}
 
+	if (!fast)
+		printf("Filled with bit-flip pattern\n");
+	digit = TOTAL_PROGRESS_DOTS;
+	dots  = 0;
+
 	for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
 		readback = mem[i];
 		if (readback != (1 << (i % 32))) {
@@ -348,24 +397,45 @@ static int memory_post_test2 (unsigned long start, unsigned long size)
 		}
 		if (i % 1024 == 0)
 			WATCHDOG_RESET ();
+		if (!fast && (i & 0xFFFFF) == 0)
+			TEST_SHOW_PROGRESS(scale, dots, digit, 1);
+	}
+	if (!fast) {
+		if (ret == 0)
+			puts("Verified OK.\n\n");
+		else
+			puts("\nFailed!\n\n");
 	}
-
 	return ret;
 }
 
-static int memory_post_test3 (unsigned long start, unsigned long size)
+static int memory_post_test3(unsigned long start, unsigned long size, int fast)
 {
 	unsigned long i;
 	ulong *mem = (ulong *) start;
 	ulong readback;
 	int ret = 0;
+	int digit, dots;
+	int scale;
+
+	scale = (int)(((size >> 22) + TOTAL_PROGRESS_DOTS - 1) /
+		TOTAL_PROGRESS_DOTS);
+	digit = TOTAL_PROGRESS_DOTS;
+	dots  = 0;
 
 	for (i = 0; i < size / sizeof (ulong); i++) {
 		mem[i] = i;
 		if (i % 1024 == 0)
 			WATCHDOG_RESET ();
+		if (!fast && (i & 0xFFFFF) == 0)
+			TEST_SHOW_PROGRESS(scale, dots, digit, 1);
 	}
 
+	if (!fast)
+		printf("Filled with address pattern\n");
+	digit = TOTAL_PROGRESS_DOTS;
+	dots  = 0;
+
 	for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
 		readback = mem[i];
 		if (readback != i) {
@@ -378,24 +448,45 @@ static int memory_post_test3 (unsigned long start, unsigned long size)
 		}
 		if (i % 1024 == 0)
 			WATCHDOG_RESET ();
+		if (!fast && (i & 0xFFFFF) == 0)
+			TEST_SHOW_PROGRESS(scale, dots, digit, 1);
+	}
+	if (!fast) {
+		if (ret == 0)
+			puts("Verified OK.\n\n");
+		else
+			puts("\nFailed!\n\n");
 	}
-
 	return ret;
 }
 
-static int memory_post_test4 (unsigned long start, unsigned long size)
+static int memory_post_test4(unsigned long start, unsigned long size, int fast)
 {
 	unsigned long i;
 	ulong *mem = (ulong *) start;
 	ulong readback;
 	int ret = 0;
+	int digit, dots;
+	int scale;
+
+	scale = (int)(((size >> 22) + TOTAL_PROGRESS_DOTS - 1) /
+		TOTAL_PROGRESS_DOTS);
+	digit = TOTAL_PROGRESS_DOTS;
+	dots  = 0;
 
 	for (i = 0; i < size / sizeof (ulong); i++) {
 		mem[i] = ~i;
 		if (i % 1024 == 0)
 			WATCHDOG_RESET ();
+		if (!fast && (i & 0xFFFFF) == 0)
+			TEST_SHOW_PROGRESS(scale, dots, digit, 1);
 	}
 
+	if (!fast)
+		printf("Filled with address complement pattern\n");
+	digit = TOTAL_PROGRESS_DOTS;
+	dots  = 0;
+
 	for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
 		readback = mem[i];
 		if (readback != ~i) {
@@ -408,75 +499,115 @@ static int memory_post_test4 (unsigned long start, unsigned long size)
 		}
 		if (i % 1024 == 0)
 			WATCHDOG_RESET ();
+		if (!fast && (i & 0xFFFFF) == 0)
+			TEST_SHOW_PROGRESS(scale, dots, digit, 1);
+	}
+	if (!fast) {
+		if (ret == 0)
+			puts("Verified OK.\n\n");
+		else
+			puts("\nFailed!\n\n");
 	}
-
 	return ret;
 }
 
-static int memory_post_tests (unsigned long start, unsigned long size)
+static int memory_post_tests(unsigned long start, unsigned long size, int fast)
 {
 	int ret = 0;
 
 	if (ret == 0)
-		ret = memory_post_dataline ((unsigned long long *)start);
+		ret = memory_post_dataline((unsigned long long *)start);
 	WATCHDOG_RESET ();
 	if (ret == 0)
-		ret = memory_post_addrline ((ulong *)start, (ulong *)start, size);
+		ret = memory_post_addrline((ulong *)start, (ulong *)start, size);
 	WATCHDOG_RESET ();
 	if (ret == 0)
-		ret = memory_post_addrline ((ulong *)(start + size - 8),
+		ret = memory_post_addrline((ulong *)(start + size - 8),
 					    (ulong *)start, size);
 	WATCHDOG_RESET ();
 	if (ret == 0)
-		ret = memory_post_test1 (start, size, 0x00000000);
+		ret = memory_post_test1(start, size, 0x00000000, fast);
 	WATCHDOG_RESET ();
 	if (ret == 0)
-		ret = memory_post_test1 (start, size, 0xffffffff);
+		ret = memory_post_test1(start, size, 0xffffffff, fast);
 	WATCHDOG_RESET ();
 	if (ret == 0)
-		ret = memory_post_test1 (start, size, 0x55555555);
+		ret = memory_post_test1(start, size, 0x55555555, fast);
 	WATCHDOG_RESET ();
 	if (ret == 0)
-		ret = memory_post_test1 (start, size, 0xaaaaaaaa);
+		ret = memory_post_test1(start, size, 0xaaaaaaaa, fast);
 	WATCHDOG_RESET ();
 	if (ret == 0)
-		ret = memory_post_test2 (start, size);
+		ret = memory_post_test2(start, size, fast);
 	WATCHDOG_RESET ();
 	if (ret == 0)
-		ret = memory_post_test3 (start, size);
+		ret = memory_post_test3(start, size, fast);
 	WATCHDOG_RESET ();
 	if (ret == 0)
-		ret = memory_post_test4 (start, size);
+		ret = memory_post_test4(start, size, fast);
 	WATCHDOG_RESET ();
 
 	return ret;
 }
 
-int memory_post_test (int flags)
+__attribute__((weak))
+int arch_memory_test_prepare(u32 *vstart, u32 *size, phys_addr_t *phys_offset)
 {
-	int ret = 0;
 	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 = (bd->bi_memsize >= 256 << 20 ?
+			256 << 20 : bd->bi_memsize) - (1 << 20);
 	/* Limit area to be tested with the board info struct */
-	if (CONFIG_SYS_SDRAM_BASE + memsize > (ulong)bd)
-		memsize = (ulong)bd - CONFIG_SYS_SDRAM_BASE;
+	if ((*vstart) + (*size) > (ulong)bd)
+		*size = (ulong)bd - CONFIG_SYS_SDRAM_BASE;
+	return 0;
+}
+
+__attribute__((weak))
+int arch_memory_test_advance(u32 *vstart, u32 *size, phys_addr_t *phys_offset)
+{
+	return 1;
+}
 
-	if (flags & POST_SLOWTEST) {
-		ret = memory_post_tests (CONFIG_SYS_SDRAM_BASE, memsize);
-	} else {			/* POST_NORMAL */
+__attribute__((weak))
+int arch_memory_test_cleanup(u32 *vstart, u32 *size, phys_addr_t *phys_offset)
+{
+	return 0;
+}
 
-		unsigned long i;
+__attribute__((weak))
+void arch_memory_failure_handle(void)
+{
+	return;
+}
 
-		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 fast, ret = 0;
+	phys_addr_t phys_offset = 0;
+	u32 memsize, vstart;
+	if (hwconfig("memtest"))
+		fast = !hwconfig_arg_cmp("memtest", "slow");
+	else
+		fast = 1;
+
+	arch_memory_test_prepare(&vstart, &memsize, &phys_offset);
+	do {
+		if ((!fast) || (flags & POST_SLOWTEST)) {
+			ret = memory_post_tests(vstart, memsize, fast);
+		} else {			/* POST_NORMAL */
+			unsigned long i;
+			for (i = 0; i < (memsize >> 20) && ret == 0; i++) {
+				if (ret == 0)
+					ret = memory_post_tests(i << 20, 0x800, fast);
+				if (ret == 0)
+					ret = memory_post_tests((i << 20) + 0xff800, 0x800, fast);
+			}
 		}
-	}
-
+	} 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;
 }
 
-- 
1.7.0.4




More information about the U-Boot mailing list