[U-Boot-Users] [PATCH] fix the incorrect dcbz operation of 83xx

Liu Dave-r63238 DaveLiu at freescale.com
Fri Jul 21 11:50:45 CEST 2006


All,

The 834x Rev1.1 silicon has one bug inside. The issue is when the dcache
locked with HID0[DLOCK], the dcbz instruction looks like no-op
instruction.

The right behavior of the dcache is when the dcache locked with
HID0[DLOCK],
the dcbz instruction allocates new tags in cache.

The bug is only in 834x rev1.1, PVR is 0x80830011. The 834x rev2.0 and
later
and 8360 have not this bug inside. 

So, when 834x rev2.0/8360 are working with ECC, the dcbz instruction
will
corrupt the stack in cache, the processor will checkstop reset.

However, the 834x rev1.1 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 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.
  Patch by Dave Liu, 21 July 2006



diff --git a/cpu/mpc83xx/spd_sdram.c b/cpu/mpc83xx/spd_sdram.c
index 48624fe..8eaa6f6 100644
--- a/cpu/mpc83xx/spd_sdram.c
+++ b/cpu/mpc83xx/spd_sdram.c
@@ -429,54 +429,37 @@ static __inline__ unsigned long get_tbms
 /* #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 ddr8349_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();
+       t_start = get_tbms();

-#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();
        /* 8K */
        dma_xfer((uint *)0x2000, 0x2000, (uint *)0);
        /* 16K */
diff --git a/cpu/mpc83xx/start.S b/cpu/mpc83xx/start.S
index 6e02cce..a616beb 100644
--- a/cpu/mpc83xx/start.S
+++ b/cpu/mpc83xx/start.S
@@ -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
+
 /*-------------------------------------------------------------------*/

 /*
diff --git a/include/common.h b/include/common.h
index e4637ad..955f107 100644
--- a/include/common.h
+++ b/include/common.h
@@ -384,6 +384,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);
diff --git a/include/configs/MPC8349EMDS.h
b/include/configs/MPC8349EMDS.h
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: diff.txt
Url: http://lists.denx.de/pipermail/u-boot/attachments/20060721/2ea6c5d2/attachment.txt 


More information about the U-Boot mailing list