ipq806x: Clear L2 error status register before linux boots.

Previous pending L2 cache errors are cleared during the
cleanup phase before transferring the control to linux.

Change-Id: I3a54c64049135e150c2b49b0d6de1667511b6a14
This commit is contained in:
Antony Arun T 2018-02-01 16:45:35 +05:30
parent 5a5d4fb198
commit 4b79b9c406
7 changed files with 106 additions and 2 deletions

View file

@ -16,6 +16,33 @@
#define ARMV7_DCACHE_CLEAN_INVAL_RANGE 4
#ifndef CONFIG_SYS_DCACHE_OFF
void set_l2_indirect_reg(u32 reg_addr, u32 val)
{
asm volatile ("mcr p15, 3, %[l2cpselr], c15, c0, 6\n\t"
"isb\n\t"
"mcr p15, 3, %[l2cpdr], c15, c0, 7\n\t"
"isb\n\t"
:
: [l2cpselr]"r" (reg_addr), [l2cpdr]"r" (val)
);
}
u32 get_l2_indirect_reg(u32 reg_addr)
{
u32 val;
asm volatile ("mcr p15, 3, %[l2cpselr], c15, c0, 6\n\t"
"isb\n\t"
"mrc p15, 3, %[l2cpdr], c15, c0, 7\n\t"
: [l2cpdr]"=r" (val)
: [l2cpselr]"r" (reg_addr)
);
return val;
}
/*
* Write the level and type you want to Cache Size Selection Register(CSSELR)
* to get size details from Current Cache Size ID Register(CCSIDR)

View file

@ -75,6 +75,8 @@ int cleanup_before_linux_select(int flags)
*/
cpu_cache_initialization();
clear_l2cache_err();
return 0;
}

View file

@ -62,6 +62,20 @@ int board_init(void)
int ret;
uint32_t start_blocks;
uint32_t size_blocks;
#ifdef CONFIG_IPQ_REPORT_L2ERR
u32 l2esr;
/* Record any kind of L2 errors caused during
* the previous boot stages as we are clearing
* the L2 errors before jumping to linux.
* Refer to cleanup_before_linux() */
#ifndef CONFIG_SYS_DCACHE_OFF
l2esr = get_l2_indirect_reg(L2ESR_IND_ADDR);
#endif
report_l2err(l2esr);
#endif
qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
gd->bd->bi_boot_params = QCA_BOOT_PARAMS_ADDR;
@ -249,6 +263,35 @@ int dram_init(void)
return 0;
}
#ifdef CONFIG_IPQ_REPORT_L2ERR
void report_l2err(u32 l2esr)
{
if (l2esr & L2ESR_MPDCD)
printf("L2 Master port decode error\n");
if (l2esr & L2ESR_MPSLV)
printf("L2 master port slave error\n");
if (l2esr & L2ESR_TSESB)
printf("L2 tag soft error, single-bit\n");
if (l2esr & L2ESR_TSEDB)
printf("L2 tag soft error, double-bit\n");
if (l2esr & L2ESR_DSESB)
printf("L2 data soft error, single-bit\n");
if (l2esr & L2ESR_DSEDB)
printf("L2 data soft error, double-bit\n");
if (l2esr & L2ESR_MSE)
printf("L2 modified soft error\n");
if (l2esr & L2ESR_MPLDREXNOK)
printf("L2 master port LDREX received Normal OK response\n");
}
#endif
void enable_caches(void)
{
icache_enable();
@ -259,7 +302,7 @@ void disable_caches(void)
icache_disable();
}
void clear_l2cache_err(void)
__weak void clear_l2cache_err(void)
{
return;
}

View file

@ -831,3 +831,19 @@ int ipq_get_tz_version(char *version_name, int buf_size)
snprintf(version_name, buf_size, "%s\n", version_name);
return 0;
}
void clear_l2cache_err(void)
{
unsigned int val;
#ifndef CONFIG_SYS_DCACHE_OFF
val = get_l2_indirect_reg(L2ESR_IND_ADDR);
#endif
#ifdef CONFIG_IPQ_REPORT_L2ERR
report_l2err(val);
#endif
#ifndef CONFIG_SYS_DCACHE_OFF
set_l2_indirect_reg(L2ESR_IND_ADDR, val);
#endif
}

View file

@ -42,6 +42,18 @@
*/
#define RESET_WDT_BARK_TIME (5 * RESET_WDT_BITE_TIME)
#define L2ESR_IND_ADDR (0x204)
/* L2ESR bit fields */
#define L2ESR_MPDCD BIT(0)
#define L2ESR_MPSLV BIT(1)
#define L2ESR_TSESB BIT(2)
#define L2ESR_TSEDB BIT(3)
#define L2ESR_DSESB BIT(4)
#define L2ESR_DSEDB BIT(5)
#define L2ESR_MSE BIT(6)
#define L2ESR_MPLDREXNOK BIT(8)
#define CE1_REG_USAGE (0)
#define CE1_ADM_USAGE (1)
#define CE1_RESOURCE (1)

View file

@ -778,6 +778,10 @@ void flush_dcache_range(unsigned long start, unsigned long stop);
void invalidate_dcache_range(unsigned long start, unsigned long stop);
void invalidate_dcache_all(void);
void invalidate_icache_all(void);
void set_l2_indirect_reg(u32 reg_addr, u32 val);
void clear_l2cache_err(void);
u32 get_l2_indirect_reg(u32 reg_addr);
void report_l2err(u32 l2esr);
enum {
/* Disable caches (else flush caches but leave them active) */

View file

@ -328,7 +328,7 @@ typedef struct {
/* Enabling this flag will report any L2 errors.
* By default we are disabling it */
/*#define CONFIG_IPQ_REPORT_L2ERR*/
#define CONFIG_IPQ_REPORT_L2ERR
/*
* Location in IMEM which contains the physical address of