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

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.

In message 1210973711-1855-1-git-send-email-gerickson@nuovations.com you wrote:
...
cpu/ppc4xx/start.S: Reworked code to handle the primordial stack and data area initialization when CFG_INIT_DCACHE_CS is asserted.
...
* 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.
Was there ever a useful explanation given why these boards should not be able to use DC as initial RAM?
Best regards,
Wolfgang Denk

On 5/18/08 1:38 PM, Wolfgang Denk wrote:
In message 1210973711-1855-1-git-send-email-gerickson@nuovations.com you wrote: ...
cpu/ppc4xx/start.S: Reworked code to handle the primordial stack and data area initialization when CFG_INIT_DCACHE_CS is asserted.
...
- 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.
Was there ever a useful explanation given why these boards should not be able to use DC as initial RAM?
Kilauea, Makalu and Haleakala (405EX- and 405EXr-based) can now use the data cache for the initial stack and data area with this 'dcba' change patch.
However, no clear reason has been provided as yet from the vendor as to why the 'dcba' addition was not historically required for the 405GP but is required now for the 405EX[r]. Regardless, the 'dcba' should work and, going forward, will be "more correct" on the 405GP as well.
Regards,
Grant Principal Nuovation System Designs, LLC
998 Alpine Terrace Suite 3 Sunnyvale, CA 94086-2469 US
T +1-408-749-0495 F +1-205-449-0495 M +1-408-489-5710
gerickson@nuovations.com http://www.nuovations.com/

In message C455E5F6.F3FB%gerickson@nuovations.com you wrote:
- 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.
Was there ever a useful explanation given why these boards should not be able to use DC as initial RAM?
Kilauea, Makalu and Haleakala (405EX- and 405EXr-based) can now use the data cache for the initial stack and data area with this 'dcba' change patch.
However, no clear reason has been provided as yet from the vendor as to why the 'dcba' addition was not historically required for the 405GP but is required now for the 405EX[r]. Regardless, the 'dcba' should work and, going forward, will be "more correct" on the 405GP as well.
So the comment "can't use the data cache for their primordial stack" is wrong and should be fixed?
Best regards,
Wolfgang Denk

On 5/18/08 2:23 PM, Wolfgang Denk wrote:
In message C455E5F6.F3FB%gerickson@nuovations.com you wrote:
- 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.
Was there ever a useful explanation given why these boards should not be able to use DC as initial RAM?
Kilauea, Makalu and Haleakala (405EX- and 405EXr-based) can now use the data cache for the initial stack and data area with this 'dcba' change patch.
However, no clear reason has been provided as yet from the vendor as to why the 'dcba' addition was not historically required for the 405GP but is required now for the 405EX[r]. Regardless, the 'dcba' should work and, going forward, will be "more correct" on the 405GP as well.
So the comment "can't use the data cache for their primordial stack" is wrong and should be fixed?
While it is pessimistic, it may not be wrong as I don't have an exhaustive suite of chips and boards at my disposal to test.
As the code stands, should all my patches submitted for this issue get integrated, users will still have the less-than-optimal option of setting up SDRAM in ext_bus_cntlr_init should it be necessary.
Regards,
Grant Principal Nuovation System Designs, LLC
998 Alpine Terrace Suite 3 Sunnyvale, CA 94086-2469 US
T +1-408-749-0495 F +1-205-449-0495 M +1-408-489-5710
gerickson@nuovations.com http://www.nuovations.com/
participants (2)
-
Grant Erickson
-
Wolfgang Denk