[U-Boot-Users] [PATCH] PPC40x: Rework CFG_INIT_DCACHE_CS Block to Avoid Machine Checks

Grant Erickson
2008-05-16T21:35:11Z

This patch lays the ground work for moving out-of-assembly and unifying the SDRAM initialization code for PowerPC 405EX[r]-based boards.

include/ppc405.h:
Wrapped casts in EBC mnemonics with a macro such that the mnemonics can be used from assembly as well as from C.

cpu/ppc4xx/start.S:
Reworked code to handle the primordial stack and data area initialization when CFG_INIT_DCACHE_CS is asserted.

The most important change was the addition of a 'dcba' loop (per-AMCC) to preallocate data cache blocks to be used for such a purpose. In addition, other changes include replacing magic numbers with the approriate mnemonics to improve code readability and self-documentation.

Tested On:
AMCC "Haleakala" with:
CFG_SDRAM_BASE=0x00000000
CFG_INIT_DCACHE_CS=4
CFG_INIT_RAM_ADDR=(CFG_SDRAM_BASE + (1 << 30))
CFG_INIT_RAM_END=(4 << 10)

Signed-off-by: Grant Erickson <gerickson@nuovations.com>
---
include/ppc405.h | 45 +++++++++++++++++++++++++++++++++++----------
cpu/ppc4xx/start.S | 124 +++++++++++++++++++++++++++++++++++++++-------------
2 files changed, 128 insertions(+), 41 deletions(-)

diff --git a/include/ppc405.h b/include/ppc405.h
index 009aa68..d02eb71 100644
--- a/include/ppc405.h
+++ b/include/ppc405.h
@@ -25,6 +25,12 @@
#define PPC_REG_BITS 32
#define PPC_REG_VAL(bit, value) ((value) << ((PPC_REG_BITS - 1) - (bit)))

+#ifndef __ASSEMBLY__
+#define static_cast(type, val) (type)(val)
+#else
+#define static_cast(type, val) (val)
+#endif
+
#ifndef CONFIG_IOP480
#define CFG_DCACHE_SIZE (16 << 10) /* For AMCC 405 CPUs */
#else
@@ -371,7 +377,8 @@

/* Bank Configuration Register */
#define EBC_BXCR_BAS_MASK PPC_REG_VAL(11, 0xFFF)
-#define EBC_BXCR_BAS_ENCODE(n) ((((unsigned long)(n))&EBC_BXCR_BAS_MASK)<<0)
+#define EBC_BXCR_BAS_ENCODE(n) (((static_cast(unsigned long, n)) & \
+ EBC_BXCR_BAS_MASK) << 0)
#define EBC_BXCR_BS_MASK PPC_REG_VAL(14, 0x7)
#define EBC_BXCR_BS_1MB PPC_REG_VAL(14, 0x0)
#define EBC_BXCR_BS_2MB PPC_REG_VAL(14, 0x1)
@@ -394,9 +401,15 @@
/* Bank Access Parameter Register */
#define EBC_BXAP_BME_ENABLED PPC_REG_VAL(0, 0x1)
#define EBC_BXAP_BME_DISABLED PPC_REG_VAL(0, 0x0)
-#define EBC_BXAP_TWT_ENCODE(n) PPC_REG_VAL(8, ((unsigned long)(n)) & 0xFF)
-#define EBC_BXAP_FWT_ENCODE(n) PPC_REG_VAL(5, ((unsigned long)(n)) & 0x1F)
-#define EBC_BXAP_BWT_ENCODE(n) PPC_REG_VAL(8, ((unsigned long)(n)) & 0x7)
+#define EBC_BXAP_TWT_ENCODE(n) PPC_REG_VAL(8, \
+ (static_cast(unsigned long, n)) \
+ & 0xFF)
+#define EBC_BXAP_FWT_ENCODE(n) PPC_REG_VAL(5, \
+ (static_cast(unsigned long, n)) \
+ & 0x1F)
+#define EBC_BXAP_BWT_ENCODE(n) PPC_REG_VAL(8, \
+ (static_cast(unsigned long, n)) \
+ & 0x7)
#define EBC_BXAP_BCE_DISABLE PPC_REG_VAL(9, 0x0)
#define EBC_BXAP_BCE_ENABLE PPC_REG_VAL(9, 0x1)
#define EBC_BXAP_BCT_MASK PPC_REG_VAL(11, 0x3)
@@ -404,11 +417,21 @@
#define EBC_BXAP_BCT_4TRANS PPC_REG_VAL(11, 0x1)
#define EBC_BXAP_BCT_8TRANS PPC_REG_VAL(11, 0x2)
#define EBC_BXAP_BCT_16TRANS PPC_REG_VAL(11, 0x3)
-#define EBC_BXAP_CSN_ENCODE(n) PPC_REG_VAL(13, ((unsigned long)(n)) & 0x3)
-#define EBC_BXAP_OEN_ENCODE(n) PPC_REG_VAL(15, ((unsigned long)(n)) & 0x3)
-#define EBC_BXAP_WBN_ENCODE(n) PPC_REG_VAL(17, ((unsigned long)(n)) & 0x3)
-#define EBC_BXAP_WBF_ENCODE(n) PPC_REG_VAL(19, ((unsigned long)(n)) & 0x3)
-#define EBC_BXAP_TH_ENCODE(n) PPC_REG_VAL(22, ((unsigned long)(n)) & 0x7)
+#define EBC_BXAP_CSN_ENCODE(n) PPC_REG_VAL(13, \
+ (static_cast(unsigned long, n)) \
+ & 0x3)
+#define EBC_BXAP_OEN_ENCODE(n) PPC_REG_VAL(15, \
+ (static_cast(unsigned long, n)) \
+ & 0x3)
+#define EBC_BXAP_WBN_ENCODE(n) PPC_REG_VAL(17, \
+ (static_cast(unsigned long, n)) \
+ & 0x3)
+#define EBC_BXAP_WBF_ENCODE(n) PPC_REG_VAL(19, \
+ (static_cast(unsigned long, n)) \
+ & 0x3)
+#define EBC_BXAP_TH_ENCODE(n) PPC_REG_VAL(22, \
+ (static_cast(unsigned long, n)) \
+ & 0x7)
#define EBC_BXAP_RE_ENABLED PPC_REG_VAL(23, 0x1)
#define EBC_BXAP_RE_DISABLED PPC_REG_VAL(23, 0x0)
#define EBC_BXAP_SOR_DELAYED PPC_REG_VAL(24, 0x0)
@@ -453,7 +476,9 @@
#define EBC_CFG_PME_DISABLE PPC_REG_VAL(14, 0x0)
#define EBC_CFG_PME_ENABLE PPC_REG_VAL(14, 0x1)
#define EBC_CFG_PMT_MASK PPC_REG_VAL(19, 0x1F)
-#define EBC_CFG_PMT_ENCODE(n) PPC_REG_VAL(19, ((unsigned long)(n)) & 0x1F)
+#define EBC_CFG_PMT_ENCODE(n) PPC_REG_VAL(19, \
+ (static_cast(unsigned long, n)) \
+ & 0x1F)
#define EBC_CFG_PR_MASK PPC_REG_VAL(21, 0x3)
#define EBC_CFG_PR_16 PPC_REG_VAL(21, 0x0)
#define EBC_CFG_PR_32 PPC_REG_VAL(21, 0x1)
diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S
index a513b45..92eb925 100644
--- a/cpu/ppc4xx/start.S
+++ b/cpu/ppc4xx/start.S
@@ -108,6 +108,34 @@
# define PBxAP pb7ap
# define PBxCR pb7cr
# endif
+/*
+ * Memory Bank x (nothingness) initialization CFG_INIT_RAM_ADDR + 64 MiB
+ * used as temporary stack pointer for the primordial stack
+ */
+# ifndef CFG_INIT_DCACHE_PBxAR
+# define CFG_INIT_DCACHE_PBxAR (EBC_BXAP_BME_DISABLED | \
+ EBC_BXAP_TWT_ENCODE(7) | \
+ EBC_BXAP_BCE_DISABLE | \
+ EBC_BXAP_BCT_2TRANS | \
+ EBC_BXAP_CSN_ENCODE(0) | \
+ EBC_BXAP_OEN_ENCODE(0) | \
+ EBC_BXAP_WBN_ENCODE(0) | \
+ EBC_BXAP_WBF_ENCODE(0) | \
+ EBC_BXAP_TH_ENCODE(2) | \
+ EBC_BXAP_RE_DISABLED | \
+ EBC_BXAP_SOR_NONDELAYED | \
+ EBC_BXAP_BEM_WRITEONLY | \
+ EBC_BXAP_PEN_DISABLED)
+# endif /* CFG_INIT_DCACHE_PBxAR */
+# ifndef CFG_INIT_DCACHE_PBxCR
+# define CFG_INIT_DCACHE_PBxCR (EBC_BXCR_BAS_ENCODE(CFG_INIT_RAM_ADDR) | \
+ EBC_BXCR_BS_64MB | \
+ EBC_BXCR_BU_RW | \
+ EBC_BXCR_BW_16BIT)
+# endif /* CFG_INIT_DCACHE_PBxCR */
+# ifndef CFG_INIT_RAM_PATTERN
+# define CFG_INIT_RAM_PATTERN 0xDEADDEAD
+# endif
#endif /* CFG_INIT_DCACHE_CS */

#if (defined(CFG_INIT_RAM_DCACHE) && (CFG_INIT_RAM_END > (4 << 10)))
@@ -922,9 +950,9 @@ _start:
#endif
#if !(defined(CFG_INIT_DCACHE_CS) || defined(CFG_TEMP_STACK_OCM))
/*
- * Boards like the Kilauea (405EX) don't have OCM and can't use
- * DCache for init-ram. So setup stack here directly after the
- * SDRAM is initialized.
+ * For boards that don't have OCM and can't use the data cache
+ * for their primordial stack, setup stack here directly after the
+ * SDRAM is initialized in ext_bus_cntlr_init.
*/
lis r1, CFG_INIT_RAM_ADDR at h
ori r1,r1,CFG_INIT_SP_OFFSET /* set up the stack in SDRAM */
@@ -1043,47 +1071,81 @@ start_ram:
/* Setup temporary stack in DCACHE or OCM if needed for SDRAM SPD. */
/*----------------------------------------------------------------------- */
#ifdef CFG_INIT_DCACHE_CS
- /*----------------------------------------------------------------------- */
- /* Memory Bank x (nothingness) initialization 1GB+64MEG */
- /* used as temporary stack pointer for stage0 */
- /*----------------------------------------------------------------------- */
- li r4,PBxAP
- mtdcr ebccfga,r4
- lis r4,0x0380
- ori r4,r4,0x0480
- mtdcr ebccfgd,r4
-
- addi r4,0,PBxCR
- mtdcr ebccfga,r4
- lis r4,0x400D
- ori r4,r4,0xa000
- mtdcr ebccfgd,r4
+ li r4, PBxAP
+ mtdcr ebccfga, r4
+ lis r4, CFG_INIT_DCACHE_PBxAR at h
+ ori r4, r4, CFG_INIT_DCACHE_PBxAR at l
+ mtdcr ebccfgd, r4
+
+ addi r4, 0, PBxCR
+ mtdcr ebccfga, r4
+ lis r4, CFG_INIT_DCACHE_PBxCR at h
+ ori r4, r4, CFG_INIT_DCACHE_PBxCR at l
+ mtdcr ebccfgd, r4

/* turn on data cache for this region */
- lis r4,0x0080
+ lis r4, 0x0080
mtdccr r4

- /* set stack pointer and clear stack to known value */
+ /*
+ * Preallocate data cache lines to be used to avoid a subsequent
+ * cache miss and an ensuing machine check exception when exceptions
+ * are enabled.
+ */
+ li r0, 0

- lis r1,CFG_INIT_RAM_ADDR at h
- ori r1,r1,CFG_INIT_SP_OFFSET at l
+ lis r3, CFG_INIT_RAM_ADDR at h
+ ori r3, r3, CFG_INIT_RAM_ADDR at l
+
+ lis r4, CFG_INIT_RAM_END at h
+ ori r4, r4, CFG_INIT_RAM_END at l
+
+ /*
+ * Convert the size, in bytes, to the number of cache lines/blocks
+ * to preallocate.
+ */
+ clrlwi. r5, r4, (32 - L1_CACHE_SHIFT)
+ srwi r5, r4, L1_CACHE_SHIFT
+ beq ..load_counter
+ addi r5, r5, 0x0001
+..load_counter:
+ mtctr r5

- li r4,2048 /* we store 2048 words to stack */
+ /* Preallocate the computed number of cache blocks. */
+..alloc_dcache_block:
+ dcba r0, r3
+ addi r3, r3, L1_CACHE_BYTES
+ bdnz ..alloc_dcache_block
+ sync
+
+ /*
+ * Load the initial stack pointer and data area and convert the size,
+ * in bytes, to the number of words to initialize to a known value.
+ */
+ lis r1, CFG_INIT_RAM_ADDR at h
+ ori r1, r1, CFG_INIT_SP_OFFSET@l
+
+ lis r4, (CFG_INIT_RAM_END >> 2)@h
+ ori r4, r4, (CFG_INIT_RAM_END >> 2)@l
mtctr r4

- lis r2,CFG_INIT_RAM_ADDR at h /* we also clear data area */
- ori r2,r2,CFG_INIT_RAM_END at l /* so cant copy value from r1 */
+ lis r2, CFG_INIT_RAM_ADDR at h
+ ori r2, r2, CFG_INIT_RAM_END at l

- lis r4,0xdead /* we store 0xdeaddead in the stack */
- ori r4,r4,0xdead
+ lis r4, CFG_INIT_RAM_PATTERN at h
+ ori r4, r4, CFG_INIT_RAM_PATTERN at l

..stackloop:
- stwu r4,-4(r2)
+ stwu r4, -4(r2)
bdnz ..stackloop

- li r0, 0 /* Make room for stack frame header and */
- stwu r0, -4(r1) /* clear final stack frame so that */
- stwu r0, -4(r1) /* stack backtraces terminate cleanly */
+ /*
+ * Make room for stack frame header and clear final stack frame so
+ * that stack backtraces terminate cleanly.
+ */
+ stwu r0, -4(r1)
+ stwu r0, -4(r1)
+
/*
* Set up a dummy frame to store reset vector as return address.
* this causes stack underflow to reset board.
--
1.5.4.3