[U-Boot] [RFC/PATCH 2/3] mtest: Add optional support for DMA memory test

Peter Tyser ptyser at xes-inc.com
Thu May 21 19:21:28 CEST 2009


Add a basic memory test which uses a DMA engine to perform a memory
copy.  The DMA copies generally result in burst transactions to SDRAM
which can otherwise be hard to generate on boards which don't have
their data cache enabled.

The DMA memory test is enabled when CONFIG_SYS_ALT_MEMTEST and
CONFIG_SYS_DMA_MEMTEST are defined and requires dmacpy() to be
implemented.

Signed-off-by: Peter Tyser <ptyser at xes-inc.com>
---
 common/cmd_mem.c |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/common/cmd_mem.c b/common/cmd_mem.c
index 2d4fc2a..9e6ee4b 100644
--- a/common/cmd_mem.c
+++ b/common/cmd_mem.c
@@ -618,6 +618,65 @@ int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 }
 #endif /* CONFIG_LOOPW */
 
+#if (defined(CONFIG_SYS_ALT_MEMTEST) && defined(CONFIG_SYS_DMA_MEMTEST))
+/*
+ * DMA memory test: Fill the 1st half of the test region with a known,
+ * semi random pattern, DMA it to the 2nd half of the test region,
+ * and verify region 2.  The DMA memory test is useful in
+ * stressing memory as it generally results in bursts which are otherwise
+ * difficult to generate if testing SDRAM before caches are enabled
+ * or enabling caches makes a board unstable.
+ */
+int memtest_dma(vu_long *start, vu_long *end)
+{
+	ulong len = ((ulong)end - (ulong)start) / 2;
+	ulong *halfway = (ulong*)(((ulong)start) + len);
+	ulong rand;
+	ulong readback;
+	ulong pattern;
+	vu_long	*addr;
+	ulong val;
+	int i;
+
+	/* Generate a random number ala K&R */
+	rand = get_timer(0) * 1103515245 + 12345;
+	pattern = (rand % 0x10000) << 16;
+	rand = rand * 1103515245 + 12345;
+	pattern |= (rand % 0x10000);
+
+	for (i = 0; i < 2; i++) {
+		/* Fill 1st half of test region with a known pattern */
+		for (addr = start, val = pattern; addr < halfway; addr++) {
+			WATCHDOG_RESET();
+			*addr = val;
+			val = (val & 0x80000000) ? -val : ~val;
+		}
+
+		/* Perform the transfer to fill in 2nd half of test region */
+		dmacpy(halfway, (void*)start, len);
+		WATCHDOG_RESET();
+
+		/* Verify 2nd half of the test region */
+		for (addr = halfway, val = pattern; addr < end; addr++) {
+			WATCHDOG_RESET();
+			readback = *addr;
+			if (readback != val) {
+				printf ("\nFAILURE: DMA memory test @ %p:"
+					" expected 0x%.8lx, actual 0x%.8lx\n",
+					addr, readback, val);
+				return 1;
+			}
+			val = (val & 0x80000000) ? -val : ~val;
+		}
+
+		/* Invert pattern for 2nd iteration */
+		pattern = ~pattern;
+	}
+
+	return 0;
+}
+#endif
+
 /*
  * Perform a memory test. A more complete alternative test can be
  * configured using CONFIG_SYS_ALT_MEMTEST. The complete test loops until
@@ -883,8 +942,14 @@ int do_mem_mtest (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 		    }
 		    start[offset] = 0;
 		}
+
+#if defined(CONFIG_SYS_DMA_MEMTEST)
+		if (memtest_dma(start, end))
+			return 1;
+#endif
 	}
 
+
 #else /* The original, quickie test */
 	incr = 1;
 	for (;;) {
-- 
1.6.2.1



More information about the U-Boot mailing list