mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-21 14:41:31 +00:00
mpc83xx: Fix the incorrect dcbz operation
The 834x rev1.x silicon has one CPU5 errata. The issue is when the data cache locked with HID0[DLOCK], the dcbz instruction looks like no-op inst. The right behavior of the data cache is when the data cache Locked with HID0[DLOCK], the dcbz instruction allocates new tags in cache. The 834x rev3.0 and later and 8360 have not this bug inside. So, when 834x rev3.0/8360 are working with ECC, the dcbz instruction will corrupt the stack in cache, the processor will checkstop reset. However, the 834x rev1.x can work with ECC with these code, because the sillicon has this cache bug. The dcbz will not corrupt the stack in cache. Really, it is the fault code running on fault sillicon. This patch fix the incorrect dcbz operation. Instead of CPU FP writing to initialise the ECC. CHANGELOG: * Fix the incorrect dcbz operation instead of CPU FP writing to initialise the ECC memory. Otherwise, it will corrupt the stack in cache, The processor will checkstop reset. Signed-off-by: Dave Liu <daveliu@freescale.com>
This commit is contained in:
parent
bf0b542d67
commit
90f30a710a
4 changed files with 39 additions and 34 deletions
|
@ -535,6 +535,7 @@ int do_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||||
|
|
||||||
/* write memory location injecting errors */
|
/* write memory location injecting errors */
|
||||||
ppcDWstore((u32 *) i, pattern);
|
ppcDWstore((u32 *) i, pattern);
|
||||||
|
__asm__ __volatile__("sync");
|
||||||
|
|
||||||
/* disable injects */
|
/* disable injects */
|
||||||
ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN;
|
ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN;
|
||||||
|
@ -543,10 +544,12 @@ int do_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||||
|
|
||||||
/* read data, this generates ECC error */
|
/* read data, this generates ECC error */
|
||||||
ppcDWload((u32 *) i, ret);
|
ppcDWload((u32 *) i, ret);
|
||||||
|
__asm__ __volatile__("sync");
|
||||||
|
|
||||||
/* re-initialize memory, double word write the location again,
|
/* re-initialize memory, double word write the location again,
|
||||||
* generates new ECC code this time */
|
* generates new ECC code this time */
|
||||||
ppcDWstore((u32 *) i, writeback);
|
ppcDWstore((u32 *) i, writeback);
|
||||||
|
__asm__ __volatile__("sync");
|
||||||
}
|
}
|
||||||
enable_interrupts();
|
enable_interrupts();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -588,6 +591,7 @@ int do_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||||
* double word write the location again,
|
* double word write the location again,
|
||||||
* generates new ECC code this time */
|
* generates new ECC code this time */
|
||||||
ppcDWstore((u32 *) i, writeback);
|
ppcDWstore((u32 *) i, writeback);
|
||||||
|
__asm__ __volatile__("sync");
|
||||||
}
|
}
|
||||||
enable_interrupts();
|
enable_interrupts();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -562,54 +562,38 @@ static __inline__ unsigned long get_tbms (void)
|
||||||
/* #define CONFIG_DDR_ECC_INIT_VIA_DMA */
|
/* #define CONFIG_DDR_ECC_INIT_VIA_DMA */
|
||||||
void ddr_enable_ecc(unsigned int dram_size)
|
void ddr_enable_ecc(unsigned int dram_size)
|
||||||
{
|
{
|
||||||
uint *p;
|
|
||||||
volatile immap_t *immap = (immap_t *)CFG_IMMRBAR;
|
volatile immap_t *immap = (immap_t *)CFG_IMMRBAR;
|
||||||
volatile ddr83xx_t *ddr= &immap->ddr;
|
volatile ddr83xx_t *ddr= &immap->ddr;
|
||||||
unsigned long t_start, t_end;
|
unsigned long t_start, t_end;
|
||||||
|
register u64 *p;
|
||||||
|
register uint size;
|
||||||
|
unsigned int pattern[2];
|
||||||
#if defined(CONFIG_DDR_ECC_INIT_VIA_DMA)
|
#if defined(CONFIG_DDR_ECC_INIT_VIA_DMA)
|
||||||
uint i;
|
uint i;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
debug("Initialize a Cachline in DRAM\n");
|
|
||||||
icache_enable();
|
icache_enable();
|
||||||
|
|
||||||
#if defined(CONFIG_DDR_ECC_INIT_VIA_DMA)
|
|
||||||
/* Initialise DMA for direct Transfers */
|
|
||||||
dma_init();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
t_start = get_tbms();
|
t_start = get_tbms();
|
||||||
|
pattern[0] = 0xdeadbeef;
|
||||||
|
pattern[1] = 0xdeadbeef;
|
||||||
|
|
||||||
#if !defined(CONFIG_DDR_ECC_INIT_VIA_DMA)
|
#if !defined(CONFIG_DDR_ECC_INIT_VIA_DMA)
|
||||||
debug("DDR init: Cache flush method\n");
|
debug("ddr init: CPU FP write method\n");
|
||||||
for (p = 0; p < (uint *)(dram_size); p++) {
|
size = dram_size;
|
||||||
if (((unsigned int)p & 0x1f) == 0) {
|
for (p = 0; p < (u64*)(size); p++) {
|
||||||
ppcDcbz((unsigned long) p);
|
ppcDWstore((u32*)p, pattern);
|
||||||
}
|
|
||||||
|
|
||||||
/* write pattern to cache and flush */
|
|
||||||
*p = (unsigned int)0xdeadbeef;
|
|
||||||
|
|
||||||
if (((unsigned int)p & 0x1c) == 0x1c) {
|
|
||||||
ppcDcbf((unsigned long) p);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
__asm__ __volatile__ ("sync");
|
||||||
#else
|
#else
|
||||||
printf("DDR init: DMA method\n");
|
debug("ddr init: DMA method\n");
|
||||||
for (p = 0; p < (uint *)(8 * 1024); p++) {
|
size = 0x2000;
|
||||||
/* zero one data cache line */
|
for (p = 0; p < (u64*)(size); p++) {
|
||||||
if (((unsigned int)p & 0x1f) == 0) {
|
ppcDWstore((u32*)p, pattern);
|
||||||
ppcDcbz((unsigned long)p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* write pattern to it and flush */
|
|
||||||
*p = (unsigned int)0xdeadbeef;
|
|
||||||
|
|
||||||
if (((unsigned int)p & 0x1c) == 0x1c) {
|
|
||||||
ppcDcbf((unsigned long)p);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
__asm__ __volatile__ ("sync");
|
||||||
|
|
||||||
|
/* Initialise DMA for direct transfer */
|
||||||
|
dma_init();
|
||||||
|
/* Start DMA to transfer */
|
||||||
dma_xfer((uint *)0x2000, 0x2000, (uint *)0); /* 8K */
|
dma_xfer((uint *)0x2000, 0x2000, (uint *)0); /* 8K */
|
||||||
dma_xfer((uint *)0x4000, 0x4000, (uint *)0); /* 16K */
|
dma_xfer((uint *)0x4000, 0x4000, (uint *)0); /* 16K */
|
||||||
dma_xfer((uint *)0x8000, 0x8000, (uint *)0); /* 32K */
|
dma_xfer((uint *)0x8000, 0x8000, (uint *)0); /* 32K */
|
||||||
|
|
|
@ -870,6 +870,18 @@ ppcDcbz:
|
||||||
dcbz r0,r3
|
dcbz r0,r3
|
||||||
blr
|
blr
|
||||||
|
|
||||||
|
.globl ppcDWstore
|
||||||
|
ppcDWstore:
|
||||||
|
lfd 1, 0(r4)
|
||||||
|
stfd 1, 0(r3)
|
||||||
|
blr
|
||||||
|
|
||||||
|
.globl ppcDWload
|
||||||
|
ppcDWload:
|
||||||
|
lfd 1, 0(r3)
|
||||||
|
stfd 1, 0(r4)
|
||||||
|
blr
|
||||||
|
|
||||||
/*-------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -402,6 +402,11 @@ void ppcSync(void);
|
||||||
void ppcDcbz(unsigned long value);
|
void ppcDcbz(unsigned long value);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined (CONFIG_MPC83XX)
|
||||||
|
void ppcDWload(unsigned int *addr, unsigned int *ret);
|
||||||
|
void ppcDWstore(unsigned int *addr, unsigned int *value);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* $(CPU)/cpu.c */
|
/* $(CPU)/cpu.c */
|
||||||
int checkcpu (void);
|
int checkcpu (void);
|
||||||
int checkicache (void);
|
int checkicache (void);
|
||||||
|
|
Loading…
Add table
Reference in a new issue