blob: f6a980a0056331ec4c9b666528a8bdd952a21ad3 [file] [log] [blame]
#include "tests.h"
#include "dump.h"
#include <diags.h>
#define DDR_ADDR_TEST_DESC "DDR Addr Bus test"
#define DDR_DATA_TEST_DESC "DDR Data Bus test"
#define DDR_PATTERN_AA_DESC "DDR Pattern 0xAA test"
#define DDR_PATTERN_55_DESC "DDR Pattern 0x55 test"
static void output_result(char *out_str, int res);
static int ddr_addr_bus(unsigned long baseaddr, unsigned long size);
static int ddr_data_bus(unsigned long baseaddr, unsigned long size);
static int ddr_pattern_aa(unsigned long baseaddr, unsigned long size);
static int ddr_pattern_55(unsigned long baseaddr, unsigned long size);
int Comcerto_ddr_test (struct diags_test_param *p)
{
int res = 0;
int no_of_tests = 0;
unsigned int baseaddr = p->params[0];
unsigned int size = p->params[1];
unsigned int flags = p->params[2];
#ifdef CONFIG_COMCERTO_VERIFICATION
int *curr = get_current_loc(); //Saving the current location to set number of tests done
#endif
if(flags & MEMTEST_ADDRBUS)
{
res = ddr_addr_bus(baseaddr, size);
output_result(DDR_ADDR_TEST_DESC, res);
no_of_tests++;
}
if(flags & MEMTEST_DATABUS)
{
res = ddr_data_bus(baseaddr, size);
output_result(DDR_DATA_TEST_DESC, res);
no_of_tests++;
}
if(flags & MEMTEST_PATTERN_AA)
{
res = ddr_pattern_aa(baseaddr, size);
output_result(DDR_PATTERN_AA_DESC, res);
no_of_tests++;
}
if(flags & MEMTEST_PATTERN_55)
{
res = ddr_pattern_55(baseaddr, size);
output_result(DDR_PATTERN_55_DESC, res);
no_of_tests++;
}
#ifdef CONFIG_COMCERTO_VERIFICATION
set_addr_val(curr, no_of_tests);
#endif
return 0;
}
static void output_result(char *out_str, int res)
{
if(res)
{
printf("%s: FAIL\n", out_str);
#ifdef CONFIG_COMCERTO_VERIFICATION
set_pass();
#endif
}
else
{
printf("%s: PASS\n", out_str);
#ifdef CONFIG_COMCERTO_VERIFICATION
set_fail();
#endif
}
}
/********************************************************************************
*
* Function Name : ddr_data_bus
*
* Description : Test the data bus wiring in an address space or memory region by performing
* a walking 1's test at a fixed address within that space or region.
*
* Return Value : Zero - if the test succeeds.
* : NonZero - the first pattern that failed.
*
* Notes : None.
*
********************************************************************************/
static int ddr_data_bus(unsigned long baseaddr, unsigned long size)
{
volatile unsigned long *test_address = 0;
unsigned long test_pattern = 0;
// Get the base address of the memory. Also take this as a memory location for testing.
test_address = (unsigned long *) baseaddr;
// Perform a walking 1's test at the selected address.
for (test_pattern = 1; test_pattern !=0; test_pattern <<= 1)
{
// Write the test pattern at the given address.
(*test_address) = test_pattern;
if ((*test_address) != test_pattern)
{
printf("\nFound test pattern error and the test pattern is 0x%08X. Returning back from line %03d of %s\n", test_pattern, __LINE__, __FUNCTION__);
return -1;
}
}
return 0;
}
/********************************************************************************
*
* Function Name : ddr_addr_bus
*
* Description : Test the address bus wiring in an address space or memory region by performing
* a walking 1's test on the relevant bits of the address and checking for aliasing.
* This test will find single-bit address failures such as stuck-high, stuck-low, and
* shorted pins. The base address and size of the region are selected by the caller.
*
* Return Value : Zero - if the test succeeds.
* : NonZero - the first address at which an aliasing problem was uncovered.
* By examining the contents of memory, it may be possible to gather
* additional information about the problem.
*
* Notes : For best results, the selected base address should have enough LSB 0's to
* guarantee single address bit changes. For example, to test a 64-Kbyte region,
* select a base address on a 64-Kbyte boundary. Also, select the region size as
* a power-of-two--if at all possible.
*
********************************************************************************/
static int ddr_addr_bus(unsigned long baseaddr, unsigned long size)
{
volatile unsigned long *test_address = 0;
unsigned long test_pattern_A = 0xAAAAAAAA;
unsigned long test_pattern_5 = 0x55555555;
unsigned long address_mask = ((size/(sizeof(baseaddr))) - 1);
unsigned long mem_offset = 0;
unsigned long test_mem_offset = 0;
// Get the base address of the memory.
test_address = (unsigned long *) baseaddr;
// Write the default pattern at each of the power-of-two offsets.
for (mem_offset = 1; (mem_offset & address_mask) != 0; mem_offset <<= 1)
{
*(test_address + mem_offset) = test_pattern_A;
printf("\nWrite: At address 0x%08X the value is 0x%08X\n", (test_address + mem_offset), test_pattern_A);
}
// Check for address bits stuck high.
test_mem_offset = 0;
*(test_address + test_mem_offset) = test_pattern_5;
printf("\nWrite: At address 0x%08X the value is 0x%08X\n", (test_address + test_mem_offset), test_pattern_5);
for (mem_offset = 1; (mem_offset & address_mask) != 0; mem_offset <<= 1)
{
if (*(test_address + mem_offset) != test_pattern_A)
{
printf("\nFound test pattern error and the test pattern is 0x%08X. Returning back from line %03d of %s\n", ((unsigned long *)(test_address + mem_offset)), __LINE__, __FUNCTION__);
return -1;
}
}
// Check for address bits stuck low or shorted.
test_mem_offset = 0;
*(test_address + test_mem_offset) = test_pattern_A;
printf("\nWrite: At address 0x%08X the value is 0x%08X\n", (test_address + test_mem_offset), test_pattern_A);
for (test_mem_offset = 1; (test_mem_offset & address_mask) != 0; test_mem_offset <<= 1)
{
*(test_address + test_mem_offset) = test_pattern_5;
if (*(test_address + 0) != test_pattern_A)
{
printf("\nFound test pattern error and the test pattern is 0x%08X. Returning back from line %03d of %s\n", ((unsigned long *)(test_address + test_mem_offset)), __LINE__, __FUNCTION__);
return -1;
}
for (mem_offset = 1; (mem_offset & address_mask) != 0; mem_offset <<= 1)
{
if ( (*(test_address + mem_offset) != test_pattern_A) && (mem_offset != test_mem_offset) )
{
printf("\nFound test pattern error and the test pattern is 0x%08X. Returning back from line %03d of %s\n", ((unsigned long *)(test_address + test_mem_offset)), __LINE__, __FUNCTION__);
return -1;
}
}
*(test_address + test_mem_offset) = test_pattern_A;
printf("\nWrite: At address 0x%08X the value is 0x%08X\n", (test_address + test_mem_offset), test_pattern_A);
}
return 0;
}
/********************************************************************************
*
* Function Name : ddr_pattern_aa
*
* Description : Test the integrity of a physical memory device by performing an
* increment/decrement test over the entire region. In the process every storage
* bit in the device is tested as a zero and a one. The base address and the size
* of the region are selected by the caller.
*
* Return Value : NULL - if the test succeeds.
* : NonZero - the first address at which an incorrect value was read back.
*
* Notes : None.
*
********************************************************************************/
static int ddr_pattern_aa(unsigned long baseaddr, unsigned long size)
{
volatile unsigned long *test_address = 0;
unsigned long test_pattern = 0;
unsigned long anti_pattern = 0;
unsigned long nWords = size / sizeof(baseaddr);
unsigned long mem_offset = 0;
// Get the base address of the memory.
test_address = (unsigned long *) baseaddr;
// Get the pattern.
test_pattern = 0xAAAAAAAA;
anti_pattern = ~test_pattern;
// Fill memory with a known pattern.
for (mem_offset = 0; mem_offset < nWords; mem_offset++)
{
*(test_address + mem_offset) = test_pattern;
}
// Check each location and invert it for the second pass.
for (mem_offset = 0; mem_offset < nWords; mem_offset++)
{
if (*(test_address + mem_offset) != test_pattern)
{
printf("\nFound test pattern error at address 0x%08X", (test_address + mem_offset));
printf("\nWritten value is: 0x%08X, Read value is: 0x%08X\n", test_pattern, *(test_address + mem_offset));
return -1;
}
*(test_address + mem_offset) = anti_pattern;
}
// Check each location for the inverted pattern and zero it.
for (mem_offset = 0; mem_offset < nWords; mem_offset++)
{
if (*(test_address + mem_offset) != anti_pattern)
{
printf("\nFound test pattern error at address 0x%08X", (test_address + mem_offset));
printf("\nWritten value is: 0x%08X, Read value is: 0x%08X\n", anti_pattern, *(test_address + mem_offset));
return -1;
}
}
return 0;
}
/********************************************************************************
*
* Function Name : ddr_pattern_55
*
* Description : Test the integrity of a physical memory device by performing an
* increment/decrement test over the entire region. In the process every storage
* bit in the device is tested as a zero and a one. The base address and the size
* of the region are selected by the caller.
*
* Return Value : NULL - if the test succeeds.
* : NonZero - the first address at which an incorrect value was read back.
*
* Notes : None.
*
********************************************************************************/
static int ddr_pattern_55(unsigned long baseaddr, unsigned long size)
{
volatile unsigned long *test_address = 0;
unsigned long test_pattern = 0;
unsigned long anti_pattern = 0;
unsigned long nWords = size / sizeof(baseaddr);
unsigned long mem_offset = 0;
// Get the base address of the memory.
test_address = (unsigned long *) baseaddr;
// Get the pattern.
test_pattern = 0x55555555;
anti_pattern = ~test_pattern;
// Fill memory with a known pattern.
for (mem_offset = 0; mem_offset < nWords; mem_offset++)
{
*(test_address + mem_offset) = test_pattern;
}
// Check each location and invert it for the second pass.
for (mem_offset = 0; mem_offset < nWords; mem_offset++)
{
if (*(test_address + mem_offset) != test_pattern)
{
printf("\nFound test pattern error at address 0x%08X", (test_address + mem_offset));
printf("\nWritten value is: 0x%08X, Read value is: 0x%08X\n", test_pattern, *(test_address + mem_offset));
return -1;
}
*(test_address + mem_offset) = anti_pattern;
}
// Check each location for the inverted pattern and zero it.
for (mem_offset = 0; mem_offset < nWords; mem_offset++)
{
if (*(test_address + mem_offset) != anti_pattern)
{
printf("\nFound test pattern error at address 0x%08X", (test_address + mem_offset));
printf("\nWritten value is: 0x%08X, Read value is: 0x%08X\n", anti_pattern, *(test_address + mem_offset));
return -1;
}
}
return 0;
}