siemens: add ddr full memory test
Add siemens specific memory test. Enable it through Kconfig option SPL_CMT. The test is required from our HW team. It runs over temperature during many days: * must run indefinitively through the *whole* DDR area, so we cannot use linux memtest for example. * must write/read/check all values Signed-off-by: Enrico Leto <enrico.leto@siemens.com> Signed-off-by: Heiko Schocher <hs@denx.de>
This commit is contained in:
committed by
Fabio Estevam
parent
eceaa88ade
commit
1d02397803
@@ -14,3 +14,10 @@ config IMX_CONFIG
|
||||
default "board/siemens/capricorn/imximage.cfg"
|
||||
|
||||
endif
|
||||
|
||||
|
||||
config SPL_CMT
|
||||
bool "Enable Siemens SPL RAM test"
|
||||
depends on SPL
|
||||
help
|
||||
Enable SIemens SPL RAM test.
|
||||
|
||||
@@ -8,6 +8,7 @@ obj-y += ../common/eeprom.o
|
||||
|
||||
ifdef CONFIG_XPL_BUILD
|
||||
obj-y += spl.o
|
||||
obj-$(CONFIG_SPL_CMT) += spl_memory_test.o
|
||||
else
|
||||
obj-y += ../common/factoryset.o
|
||||
endif
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <asm/arch/iomux.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include "spl_memory_test.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
@@ -58,6 +59,10 @@ void spl_board_init(void)
|
||||
preloader_console_init();
|
||||
|
||||
puts("Normal Boot\n");
|
||||
|
||||
#if IS_ENABLED(CONFIG_SPL_CMT)
|
||||
spl_siemens_memory_full_test();
|
||||
#endif
|
||||
}
|
||||
|
||||
void spl_board_prepare_for_boot(void)
|
||||
|
||||
158
board/siemens/capricorn/spl_memory_test.c
Normal file
158
board/siemens/capricorn/spl_memory_test.c
Normal file
@@ -0,0 +1,158 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright Siemens AG 2020
|
||||
*
|
||||
* SPL Full Memory Test
|
||||
* - memory test through the full DDR area
|
||||
* - refresh over temperature torture (write all, read all)
|
||||
*
|
||||
* Remark:
|
||||
* This test has ran properly with the definition of the RAM sizes in board
|
||||
* headers. Since these headers are removed it's necessary to set the correct
|
||||
* values to PHYS_SDRAM_1_SIZE & PHYS_SDRAM_2_SIZE before to recompile.
|
||||
*
|
||||
* An alternative is to refactor the code to get the size info from system
|
||||
* controller
|
||||
*/
|
||||
|
||||
#include <init.h>
|
||||
#include <log.h>
|
||||
|
||||
/* ----- Defines ----- */
|
||||
#define CHECK_LOWER_UPPER
|
||||
|
||||
#define LEVEL2_PRINT 0x0FFFFFFF
|
||||
|
||||
/* use 0x7FFF0000 for shorter loop test */
|
||||
#define BASE_OFFSET 0x00000000
|
||||
|
||||
/* ----- Types ----- */
|
||||
struct ct_t {
|
||||
unsigned long *start;
|
||||
unsigned long *end;
|
||||
};
|
||||
|
||||
/* ----- Variables ----- */
|
||||
static struct ct_t ct;
|
||||
static unsigned long error_counter;
|
||||
|
||||
static void print_parameters(void)
|
||||
{
|
||||
printf("\nstart addr: %p\n", ct.start);
|
||||
printf("end addr : %p\n", ct.end);
|
||||
}
|
||||
|
||||
static void run_test(void)
|
||||
{
|
||||
/* moved full test in one void */
|
||||
unsigned long *address; /* 512 */
|
||||
unsigned long ebyte1;
|
||||
unsigned long ebyte2;
|
||||
unsigned int i;
|
||||
unsigned long rpattern;
|
||||
|
||||
for (i = 0; i <= 255; i++) {
|
||||
memset(&ebyte1, i, sizeof(ebyte1));
|
||||
ebyte2 = ~ebyte1;
|
||||
printf("LWord: %016lx #LWord: %016lx\n", ebyte1, ebyte2);
|
||||
|
||||
/* write all bytes -> duration ~ 150 s */
|
||||
for (address = ct.start; address <= ct.end; address++) {
|
||||
#ifdef LEVEL2_PRINT
|
||||
if (((unsigned long)address & LEVEL2_PRINT) == 0)
|
||||
printf("write to %p - %p\n", address,
|
||||
(void *)((unsigned long)address +
|
||||
LEVEL2_PRINT));
|
||||
#endif
|
||||
*address = ebyte1;
|
||||
address++;
|
||||
*address = ebyte2;
|
||||
}
|
||||
|
||||
/* check all bytes */
|
||||
for (address = ct.start; address <= ct.end; address++) {
|
||||
#ifdef LEVEL2_PRINT
|
||||
if (((unsigned long)address & LEVEL2_PRINT) == 0)
|
||||
printf("check from %p - %p\n", address,
|
||||
(void *)((unsigned long)address +
|
||||
LEVEL2_PRINT));
|
||||
#endif
|
||||
|
||||
rpattern = *address;
|
||||
if (rpattern != ebyte1) {
|
||||
error_counter++;
|
||||
printf("Error! Read: %016lX Wrote: %016lX Address: %p\n",
|
||||
rpattern, ebyte1, address);
|
||||
}
|
||||
|
||||
address++;
|
||||
rpattern = *address;
|
||||
if (rpattern != ebyte2) {
|
||||
error_counter++;
|
||||
printf("Error! Read: %016lX Wrote: %016lX Address: %p\n",
|
||||
rpattern, ebyte2, address);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CHECK_LOWER_UPPER
|
||||
void test_lower_upper(void)
|
||||
{
|
||||
/*
|
||||
* write different values at the same address of both memory areas
|
||||
* and check them
|
||||
*/
|
||||
#define TEST_ADDRESS 0x12345670UL
|
||||
#define LOWER_ADDRESS (PHYS_SDRAM_1 + TEST_ADDRESS)
|
||||
#define UPPER_ADDRESS (PHYS_SDRAM_2 + TEST_ADDRESS)
|
||||
#define LOWER_VALUE 0x0011223344556677
|
||||
#define UPPER_VALUE 0x89ab89abffeeddcc
|
||||
|
||||
*(unsigned long *)LOWER_ADDRESS = LOWER_VALUE;
|
||||
*(unsigned long *)UPPER_ADDRESS = UPPER_VALUE;
|
||||
|
||||
puts("\nlower-upper memory area test\n");
|
||||
printf("write %016lx to lower address %010lx\n", LOWER_VALUE,
|
||||
LOWER_ADDRESS);
|
||||
printf("write %016lx to upper address %010lx\n", UPPER_VALUE,
|
||||
UPPER_ADDRESS);
|
||||
printf("read %016lx from lower address %010lx\n",
|
||||
*(unsigned long *)LOWER_ADDRESS, LOWER_ADDRESS);
|
||||
printf("read %016lx from upper address %010lx\n",
|
||||
*(unsigned long *)UPPER_ADDRESS, UPPER_ADDRESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
void spl_siemens_memory_full_test(void)
|
||||
{
|
||||
unsigned long loopc = 0;
|
||||
|
||||
puts("\nSPL: memory cell test\n");
|
||||
|
||||
#ifdef CHECK_LOWER_UPPER
|
||||
if (PHYS_SDRAM_2_SIZE != 0)
|
||||
test_lower_upper();
|
||||
#endif
|
||||
|
||||
while (true) {
|
||||
/* imx8x has 2 memory areas up to 2 GB */
|
||||
|
||||
/* 1st memory area @ 0x80000000 */
|
||||
ct.start = (unsigned long *)(PHYS_SDRAM_1 + BASE_OFFSET);
|
||||
ct.end = (unsigned long *)(PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE - 1);
|
||||
print_parameters();
|
||||
run_test();
|
||||
|
||||
/* 2nd memory area @ 0x880000000 */
|
||||
if (PHYS_SDRAM_2_SIZE != 0) {
|
||||
ct.start = (unsigned long *)(PHYS_SDRAM_2 + BASE_OFFSET);
|
||||
ct.end = (unsigned long *)(PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE - 1);
|
||||
print_parameters();
|
||||
run_test();
|
||||
}
|
||||
|
||||
loopc++;
|
||||
printf("loop: %ld, errors: %ld\n\n", loopc, error_counter);
|
||||
};
|
||||
}
|
||||
7
board/siemens/capricorn/spl_memory_test.h
Normal file
7
board/siemens/capricorn/spl_memory_test.h
Normal file
@@ -0,0 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright Siemens AG 2020
|
||||
*
|
||||
*/
|
||||
|
||||
void spl_siemens_memory_full_test(void);
|
||||
Reference in New Issue
Block a user