@ -7,12 +7,15 @@
*/
# include <asm/arch/hardware.h>
# include <asm/arch/ddr3.h>
# include <asm/cache.h>
# include <asm/emif.h>
# include <common.h>
# include <command.h>
DECLARE_GLOBAL_DATA_PTR ;
# ifdef CONFIG_ARCH_KEYSTONE
# include <asm/arch/ddr3.h>
# define DDR_MIN_ADDR CONFIG_SYS_SDRAM_BASE
# define STACKSIZE (512 << 10) /* 512 KiB */
@ -21,6 +24,7 @@ DECLARE_GLOBAL_DATA_PTR;
# define ECC_END_ADDR1 (((gd->start_addr_sp - DDR_REMAP_ADDR - \
STACKSIZE ) > > 17 ) - 2 )
# endif
# define DDR_TEST_BURST_SIZE 1024
@ -153,57 +157,143 @@ static int ddr_memory_compare(u32 address1, u32 address2, u32 size)
return 0 ;
}
static int ddr_memory_ecc_err ( u32 base , u32 address , u32 ecc_err )
static void ddr_check_ecc_status ( void )
{
struct emif_reg_struct * emif = ( struct emif_reg_struct * ) EMIF1_BASE ;
u32 err_1b = readl ( & emif - > emif_1b_ecc_err_cnt ) ;
u32 int_status = readl ( & emif - > emif_irqstatus_raw_sys ) ;
int ecc_test = 0 ;
char * env ;
env = env_get ( " ecc_test " ) ;
if ( env )
ecc_test = simple_strtol ( env , NULL , 0 ) ;
puts ( " ECC test Status: \n " ) ;
if ( int_status & EMIF_INT_WR_ECC_ERR_SYS_MASK )
puts ( " \t ECC test: DDR ECC write error interrupted \n " ) ;
if ( int_status & EMIF_INT_TWOBIT_ECC_ERR_SYS_MASK )
if ( ! ecc_test )
panic ( " \t ECC test: DDR ECC 2-bit error interrupted " ) ;
if ( int_status & EMIF_INT_ONEBIT_ECC_ERR_SYS_MASK )
puts ( " \t ECC test: DDR ECC 1-bit error interrupted \n " ) ;
if ( err_1b )
printf ( " \t ECC test: 1-bit ECC err count: 0x%x \n " , err_1b ) ;
}
static int ddr_memory_ecc_err ( u32 addr , u32 ecc_err )
{
u32 value1 , value2 , value3 ;
struct emif_reg_struct * emif = ( struct emif_reg_struct * ) EMIF1_BASE ;
u32 ecc_ctrl = readl ( & emif - > emif_ecc_ctrl_reg ) ;
u32 val1 , val2 , val3 ;
debug ( " Disabling D-Cache before ECC test \n " ) ;
dcache_disable ( ) ;
invalidate_dcache_all ( ) ;
puts ( " Disabling DDR ECC ... \n " ) ;
ddr3_disable_ecc ( base ) ;
puts ( " Testing DDR ECC: \n " ) ;
puts ( " \t ECC test: Disabling DDR ECC ... \n " ) ;
writel ( 0 , & emif - > emif_ecc_ctrl_reg ) ;
value1 = __raw_readl ( address ) ;
value2 = value1 ^ ecc_err ;
__raw_writel ( value2 , address ) ;
val1 = readl ( addr ) ;
val2 = val1 ^ ecc_err ;
writel ( val2 , addr ) ;
value3 = __raw_readl ( address ) ;
printf ( " ECC err test, addr 0x%x, read data 0x%x, wrote data 0x%x, err pattern: 0x%x, read after write data 0x%x \n " ,
address , value1 , value2 , ecc_err , value3 ) ;
val3 = readl ( addr ) ;
printf ( " \t ECC test: addr 0x%x, read data 0x%x, written data 0x%x, err pattern: 0x%x, read after write data 0x%x\n " ,
addr , val1 , val2 , ecc_err , val3 ) ;
__raw_writel ( ECC_START_ADDR1 | ( ECC_END_ADDR1 < < 16 ) ,
base + KS2_DDR3_ECC_ADDR_RANGE1_OFFSET ) ;
puts ( " \t ECC test: Enabling DDR ECC ... \n " ) ;
# ifdef CONFIG_ARCH_KEYSTONE
ecc_ctrl = ECC_START_ADDR1 | ( ECC_END_ADDR1 < < 16 ) ;
writel ( ecc_ctrl , EMIF1_BASE + KS2_DDR3_ECC_ADDR_RANGE1_OFFSET ) ;
ddr3_enable_ecc ( EMIF1_BASE , 1 ) ;
# else
writel ( ecc_ctrl , & emif - > emif_ecc_ctrl_reg ) ;
# endif
puts ( " Enabling DDR ECC ... \n " ) ;
ddr3_enable_ecc ( base , 1 ) ;
val1 = readl ( addr ) ;
printf ( " \t ECC test: addr 0x%x, read data 0x%x \n " , addr , val 1) ;
value1 = __raw_readl ( address ) ;
printf ( " ECC err test, addr 0x%x, read data 0x%x \n " , address , value1 ) ;
ddr_check_ecc_status ( ) ;
debug ( " Enabling D-cache back after ECC test \n " ) ;
enable_caches ( ) ;
ddr3_check_ecc_int ( base ) ;
return 0 ;
}
static int is_addr_valid ( u32 addr )
{
struct emif_reg_struct * emif = ( struct emif_reg_struct * ) EMIF1_BASE ;
u32 start_addr , end_addr , range , ecc_ctrl ;
# ifdef CONFIG_ARCH_KEYSTONE
ecc_ctrl = EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_MASK ;
range = ECC_START_ADDR1 | ( ECC_END_ADDR1 < < 16 ) ;
# else
ecc_ctrl = readl ( & emif - > emif_ecc_ctrl_reg ) ;
range = readl ( & emif - > emif_ecc_address_range_1 ) ;
# endif
/* Check in ecc address range 1 */
if ( ecc_ctrl & EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_MASK ) {
start_addr = ( ( range & EMIF_ECC_REG_ECC_START_ADDR_MASK ) < < 16 )
+ CONFIG_SYS_SDRAM_BASE ;
end_addr = start_addr + ( range & EMIF_ECC_REG_ECC_END_ADDR_MASK )
+ 0xFFFF ;
if ( ( addr > = start_addr ) & & ( addr < = end_addr ) )
/* addr within ecc address range 1 */
return 1 ;
}
/* Check in ecc address range 2 */
if ( ecc_ctrl & EMIF_ECC_REG_ECC_ADDR_RGN_2_EN_MASK ) {
range = readl ( & emif - > emif_ecc_address_range_2 ) ;
start_addr = ( ( range & EMIF_ECC_REG_ECC_START_ADDR_MASK ) < < 16 )
+ CONFIG_SYS_SDRAM_BASE ;
end_addr = start_addr + ( range & EMIF_ECC_REG_ECC_END_ADDR_MASK )
+ 0xFFFF ;
if ( ( addr > = start_addr ) & & ( addr < = end_addr ) )
/* addr within ecc address range 2 */
return 1 ;
}
return 0 ;
}
static int is_ecc_enabled ( void )
{
struct emif_reg_struct * emif = ( struct emif_reg_struct * ) EMIF1_BASE ;
u32 ecc_ctrl = readl ( & emif - > emif_ecc_ctrl_reg ) ;
return ( ecc_ctrl & EMIF_ECC_CTRL_REG_ECC_EN_MASK ) & &
( ecc_ctrl & EMIF_ECC_REG_RMW_EN_MASK ) ;
}
static int do_ddr_test ( cmd_tbl_t * cmdtp ,
int flag , int argc , char * const argv [ ] )
{
u32 start_addr , end_addr , size , ecc_err ;
if ( ( argc = = 4 ) & & ( strncmp ( argv [ 1 ] , " ecc_err " , 8 ) = = 0 ) ) {
if ( ! ddr3_ecc_support_rmw ( KS2_DDR3A_EMIF_CTRL_BASE ) ) {
puts ( " ECC RMW isn't supported for this SOC \n " ) ;
return 1 ;
if ( ! is_ecc_enabled ( ) ) {
puts ( " ECC not enabled. Please Enable ECC any try again \n " ) ;
return CMD_RET_FAILURE ;
}
start_addr = simple_strtoul ( argv [ 2 ] , NULL , 16 ) ;
ecc_err = simple_strtoul ( argv [ 3 ] , NULL , 16 ) ;
if ( ( start_addr < CONFIG_SYS_SDRAM_BASE ) | |
( start_addr > ( CONFIG_SYS_SDRAM_BASE +
CONFIG_MAX_RAM_BANK_SIZE - 1 ) ) ) {
puts ( " Invalid address! \n " ) ;
return cmd_usage ( cmdtp ) ;
if ( ! is_addr_valid ( start_addr ) ) {
puts ( " Invalid address. Please enter ECC supported address! \n " ) ;
return CMD_RET_FAILURE ;
}
ddr_memory_ecc_err ( KS2_DDR3A_EMIF_CTRL_BASE ,
start_addr , ecc_err ) ;
ddr_memory_ecc_err ( start_addr , ecc_err ) ;
return 0 ;
}
@ -216,10 +306,10 @@ static int do_ddr_test(cmd_tbl_t *cmdtp,
if ( ( start_addr < CONFIG_SYS_SDRAM_BASE ) | |
( start_addr > ( CONFIG_SYS_SDRAM_BASE +
CONFIG_MAX_RAM_BANK_SIZE - 1 ) ) | |
get_effective_memsize ( ) - 1 ) ) | |
( end_addr < CONFIG_SYS_SDRAM_BASE ) | |
( end_addr > ( CONFIG_SYS_SDRAM_BASE +
CONFIG_MAX_RAM_BANK_SIZE - 1 ) ) | | ( start_addr > = end_addr ) ) {
get_effective_memsize ( ) - 1 ) ) | | ( start_addr > = end_addr ) ) {
puts ( " Invalid start or end address! \n " ) ;
return cmd_usage ( cmdtp ) ;
}