mpc83xx: Fix the incorrect dcbz operation
authorDave Liu <daveliu@freescale.com>
Fri, 3 Nov 2006 00:05:50 +0000 (18:05 -0600)
committerKim Phillips <kim.phillips@freescale.com>
Sat, 4 Nov 2006 01:42:22 +0000 (19:42 -0600)
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>
board/mpc8360emds/mpc8360emds.c
cpu/mpc83xx/spd_sdram.c
cpu/mpc83xx/start.S
include/common.h

index 5bbaa5cf2e9a384547bfd38e9551b0e010ee367f..a9b1d9eb32cc81dba621a770604bfd0494803787 100644 (file)
@@ -535,6 +535,7 @@ int do_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 
                                /* write memory location injecting errors */
                                ppcDWstore((u32 *) i, pattern);
+                               __asm__ __volatile__("sync");
 
                                /* disable injects */
                                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 */
                                ppcDWload((u32 *) i, ret);
+                               __asm__ __volatile__("sync");
 
                                /* re-initialize memory, double word write the location again,
                                 * generates new ECC code this time */
                                ppcDWstore((u32 *) i, writeback);
+                               __asm__ __volatile__("sync");
                        }
                        enable_interrupts();
                        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,
                                 * generates new ECC code this time */
                                ppcDWstore((u32 *) i, writeback);
+                               __asm__ __volatile__("sync");
                        }
                        enable_interrupts();
                        return 0;
index acc8c9e79b635fb42393612f18aee7ad4f317ad2..b91c6130e7847f4c9b50b893b6c37a6167cc126e 100644 (file)
@@ -562,54 +562,38 @@ static __inline__ unsigned long get_tbms (void)
 /* #define CONFIG_DDR_ECC_INIT_VIA_DMA */
 void ddr_enable_ecc(unsigned int dram_size)
 {
-       uint *p;
        volatile immap_t *immap = (immap_t *)CFG_IMMRBAR;
        volatile ddr83xx_t *ddr= &immap->ddr;
        unsigned long t_start, t_end;
+       register u64 *p;
+       register uint size;
+       unsigned int pattern[2];
 #if defined(CONFIG_DDR_ECC_INIT_VIA_DMA)
        uint i;
 #endif
-
-       debug("Initialize a Cachline in DRAM\n");
        icache_enable();
-
-#if defined(CONFIG_DDR_ECC_INIT_VIA_DMA)
-       /* Initialise DMA for direct Transfers */
-       dma_init();
-#endif
-
        t_start = get_tbms();
+       pattern[0] = 0xdeadbeef;
+       pattern[1] = 0xdeadbeef;
 
 #if !defined(CONFIG_DDR_ECC_INIT_VIA_DMA)
-       debug("DDR init: Cache flush method\n");
-       for (p = 0; p < (uint *)(dram_size); p++) {
-               if (((unsigned int)p & 0x1f) == 0) {
-                       ppcDcbz((unsigned long) p);
-               }
-
-               /* write pattern to cache and flush */
-               *p = (unsigned int)0xdeadbeef;
-
-               if (((unsigned int)p & 0x1c) == 0x1c) {
-                       ppcDcbf((unsigned long) p);
-               }
+       debug("ddr init: CPU FP write method\n");
+       size = dram_size;
+       for (p = 0; p < (u64*)(size); p++) {
+               ppcDWstore((u32*)p, pattern);
        }
+       __asm__ __volatile__ ("sync");
 #else
-       printf("DDR init: DMA method\n");
-       for (p = 0; p < (uint *)(8 * 1024); p++) {
-               /* zero one data cache line */
-               if (((unsigned int)p & 0x1f) == 0) {
-                       ppcDcbz((unsigned long)p);
-               }
-
-               /* write pattern to it and flush */
-               *p = (unsigned int)0xdeadbeef;
-
-               if (((unsigned int)p & 0x1c) == 0x1c) {
-                       ppcDcbf((unsigned long)p);
-               }
+       debug("ddr init: DMA method\n");
+       size = 0x2000;
+       for (p = 0; p < (u64*)(size); p++) {
+               ppcDWstore((u32*)p, pattern);
        }
+       __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 *)0x4000, 0x4000, (uint *)0); /* 16K */
        dma_xfer((uint *)0x8000, 0x8000, (uint *)0); /* 32K */
index a7ed3c5b2c1b5267de24c31f6e831cb7f3193434..c43835c8dcdadbe207ddca384c8c717556e436dd 100644 (file)
@@ -870,6 +870,18 @@ ppcDcbz:
        dcbz    r0,r3
        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
+
 /*-------------------------------------------------------------------*/
 
 /*
index 349d5cf726bdc833937267b97a57e2eba19c6fa9..0be8372cc5e9053becd2c5127fc06d4ea7b15656 100644 (file)
@@ -402,6 +402,11 @@ void               ppcSync(void);
 void           ppcDcbz(unsigned long value);
 #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 */
 int    checkcpu      (void);
 int    checkicache   (void);