[U-Boot] [RFC/PATCH 0/3] Add optional dma transfers to mtest

This series tries to add a DMA memory test to the mtest tests. The DMA test performs bursts to SDRAM which can be useful in stressing memory and can be difficult to produce reliably in certain circumstances (eg running with data caches disabled).
It can be enabled on 85xx and 86xx boards by defining CONFIG_FSL_DMA, CONFIG_SYS_ALT_MEMTEST, and CONFIG_SYS_DMA_MEMTEST.
Other platforms will need to support the dmacpy() function in order to enable the DMA memory test.
Peter Tyser (3): fsl_dma: Make DMA transactions snoopable mtest: Add optional support for DMA memory test XPedite5200, XPedite5370: Enable DMA memory test
common/cmd_mem.c | 65 +++++++++++++++++++++++++++++++++++++++++ drivers/dma/fsl_dma.c | 4 +- include/configs/XPEDITE5200.h | 4 ++- include/configs/XPEDITE5370.h | 2 + 4 files changed, 72 insertions(+), 3 deletions(-)

Make DMA transactions snoopable so that CPUs can keep caches up-to-date. This allows dma transactions to be used for operations such as memory copies without any additional cache control operations.
Signed-off-by: Peter Tyser ptyser@xes-inc.com --- drivers/dma/fsl_dma.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/fsl_dma.c b/drivers/dma/fsl_dma.c index b7497b5..572f8b6 100644 --- a/drivers/dma/fsl_dma.c +++ b/drivers/dma/fsl_dma.c @@ -72,8 +72,8 @@ static uint dma_check(void) { void dma_init(void) { volatile fsl_dma_t *dma = &dma_base->dma[0];
- out_be32(&dma->satr, FSL_DMA_SATR_SREAD_NO_SNOOP); - out_be32(&dma->datr, FSL_DMA_DATR_DWRITE_NO_SNOOP); + out_be32(&dma->satr, FSL_DMA_SATR_SREAD_SNOOP); + out_be32(&dma->datr, FSL_DMA_DATR_DWRITE_SNOOP); out_be32(&dma->sr, 0xffffffff); /* clear any errors */ dma_sync(); }

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@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 (;;) {

Enable the Freescale DMA driver and DMA portion of mtest for the XPedite5200 and XPedite5370 boards
Signed-off-by: Peter Tyser ptyser@xes-inc.com --- include/configs/XPEDITE5200.h | 4 +++- include/configs/XPEDITE5370.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/include/configs/XPEDITE5200.h b/include/configs/XPEDITE5200.h index 89ab692..11c9690 100644 --- a/include/configs/XPEDITE5200.h +++ b/include/configs/XPEDITE5200.h @@ -88,6 +88,7 @@ * Diagnostics */ #define CONFIG_SYS_ALT_MEMTEST +#define CONFIG_SYS_DMA_MEMTEST #define CONFIG_SYS_MEMTEST_START 0x10000000 #define CONFIG_SYS_MEMTEST_END 0x20000000
@@ -361,7 +362,8 @@ #define CONFIG_FIT 1 #define CONFIG_FIT_VERBOSE 1 #define CONFIG_INTEGRITY /* support booting INTEGRITY OS */ -#define CONFIG_INTERRUPTS /* enable pci, srio, ddr interrupts */ +#define CONFIG_INTERRUPTS /* enable pci, srio, ddr interrupts */ +#define CONFIG_FSL_DMA /* Enable Freescale DMA engine */
/* * For booting Linux, the board info and command line data diff --git a/include/configs/XPEDITE5370.h b/include/configs/XPEDITE5370.h index 536e063..10e00d8 100644 --- a/include/configs/XPEDITE5370.h +++ b/include/configs/XPEDITE5370.h @@ -100,6 +100,7 @@ extern unsigned long get_board_ddr_clk(unsigned long dummy); * Diagnostics */ #define CONFIG_SYS_ALT_MEMTEST +#define CONFIG_SYS_DMA_MEMTEST #define CONFIG_SYS_MEMTEST_START 0x10000000 #define CONFIG_SYS_MEMTEST_END 0x20000000
@@ -405,6 +406,7 @@ extern unsigned long get_board_ddr_clk(unsigned long dummy); #define CONFIG_FIT 1 #define CONFIG_FIT_VERBOSE 1 #define CONFIG_INTEGRITY /* support booting INTEGRITY OS */ +#define CONFIG_FSL_DMA /* Enable Freescale DMA engine */
/* * For booting Linux, the board info and command line data

On Thu, 2009-05-21 at 12:21 -0500, Peter Tyser wrote:
This series tries to add a DMA memory test to the mtest tests. The DMA test performs bursts to SDRAM which can be useful in stressing memory and can be difficult to produce reliably in certain circumstances (eg running with data caches disabled).
It can be enabled on 85xx and 86xx boards by defining CONFIG_FSL_DMA, CONFIG_SYS_ALT_MEMTEST, and CONFIG_SYS_DMA_MEMTEST.
Other platforms will need to support the dmacpy() function in order to enable the DMA memory test.
Is there any interest in this feature, or any chance it will be merged? If so, I'll clean it up a bit and resubmit.
Thanks, Peter

On Wed, Jul 01, 2009 at 10:59:47AM -0500, Peter Tyser wrote:
On Thu, 2009-05-21 at 12:21 -0500, Peter Tyser wrote:
This series tries to add a DMA memory test to the mtest tests. The DMA test performs bursts to SDRAM which can be useful in stressing memory and can be difficult to produce reliably in certain circumstances (eg running with data caches disabled).
It can be enabled on 85xx and 86xx boards by defining CONFIG_FSL_DMA, CONFIG_SYS_ALT_MEMTEST, and CONFIG_SYS_DMA_MEMTEST.
Other platforms will need to support the dmacpy() function in order to enable the DMA memory test.
Is there any interest in this feature, or any chance it will be merged? If so, I'll clean it up a bit and resubmit.
I thought it was useful, primarily in testing your Freescale DMA patches.
I'm not sure how much this test stresses the memory chips (as compared to Linux). If it is reasonably close, then I think it is a very useful piece of code to have. Linux is a lot more code to wade through compared to U-Boot when things aren't working.
Ira
participants (2)
-
Ira Snyder
-
Peter Tyser