
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@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@h + ori r4, r4, CFG_INIT_DCACHE_PBxAR@l + mtdcr ebccfgd, r4 + + addi r4, 0, PBxCR + mtdcr ebccfga, r4 + lis r4, CFG_INIT_DCACHE_PBxCR@h + ori r4, r4, CFG_INIT_DCACHE_PBxCR@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@h - ori r1,r1,CFG_INIT_SP_OFFSET@l + lis r3, CFG_INIT_RAM_ADDR@h + ori r3, r3, CFG_INIT_RAM_ADDR@l + + lis r4, CFG_INIT_RAM_END@h + ori r4, r4, CFG_INIT_RAM_END@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@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@h /* we also clear data area */ - ori r2,r2,CFG_INIT_RAM_END@l /* so cant copy value from r1 */ + lis r2, CFG_INIT_RAM_ADDR@h + ori r2, r2, CFG_INIT_RAM_END@l
- lis r4,0xdead /* we store 0xdeaddead in the stack */ - ori r4,r4,0xdead + lis r4, CFG_INIT_RAM_PATTERN@h + ori r4, r4, CFG_INIT_RAM_PATTERN@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.