From 33f57bd553edf29dffef5a6c7d76e169c79a6049 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 26 Mar 2010 15:14:43 -0500 Subject: [PATCH 1/2] 85xx: Fix enabling of L1 cache parity on secondary cores Use the same code between primary and secondary cores to init the L1 cache. We were not enabling cache parity on the secondary cores. Also, reworked the L1 cache init code to match the e500mc L2 init code that first invalidates the cache and locks. Than enables the cache and makes sure its enabled before continuing. Signed-off-by: Kumar Gala --- cpu/mpc85xx/release.S | 38 ++++++++++++++++++++++++++++++-------- cpu/mpc85xx/start.S | 38 +++++++++++++++++++++++++++++++++----- include/asm-ppc/processor.h | 2 ++ 3 files changed, 65 insertions(+), 13 deletions(-) diff --git a/cpu/mpc85xx/release.S b/cpu/mpc85xx/release.S index 00c4c54..dab784e 100644 --- a/cpu/mpc85xx/release.S +++ b/cpu/mpc85xx/release.S @@ -70,18 +70,40 @@ __secondary_start_page: mttbu r3 /* Enable/invalidate the I-Cache */ - mfspr r0,SPRN_L1CSR1 - ori r0,r0,(L1CSR1_ICFI|L1CSR1_ICE) - mtspr SPRN_L1CSR1,r0 + lis r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@h + ori r2,r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@l + mtspr SPRN_L1CSR1,r2 +1: + mfspr r3,SPRN_L1CSR1 + and. r1,r3,r2 + bne 1b + + lis r3,(L1CSR1_CPE|L1CSR1_ICE)@h + ori r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l + mtspr SPRN_L1CSR1,r3 isync +2: + mfspr r3,SPRN_L1CSR1 + andi. r1,r3,L1CSR1_ICE@l + beq 2b /* Enable/invalidate the D-Cache */ - mfspr r0,SPRN_L1CSR0 - ori r0,r0,(L1CSR0_DCFI|L1CSR0_DCE) - msync - isync - mtspr SPRN_L1CSR0,r0 + lis r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@h + ori r2,r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@l + mtspr SPRN_L1CSR0,r2 +1: + mfspr r3,SPRN_L1CSR0 + and. r1,r3,r2 + bne 1b + + lis r3,(L1CSR0_CPE|L1CSR0_DCE)@h + ori r3,r3,(L1CSR0_CPE|L1CSR0_DCE)@l + mtspr SPRN_L1CSR0,r3 isync +2: + mfspr r3,SPRN_L1CSR0 + andi. r1,r3,L1CSR0_DCE@l + beq 2b #define toreset(x) (x - __secondary_start_page + 0xfffff000) diff --git a/cpu/mpc85xx/start.S b/cpu/mpc85xx/start.S index 386fa81..af18c1c 100644 --- a/cpu/mpc85xx/start.S +++ b/cpu/mpc85xx/start.S @@ -108,13 +108,41 @@ _start_e500: mtspr L1CSR2,r2 #endif - lis r2,L1CSR0_CPE@H /* enable parity */ - ori r2,r2,L1CSR0_DCE - mtspr L1CSR0,r2 /* enable L1 Dcache */ + /* Enable/invalidate the I-Cache */ + lis r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@h + ori r2,r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@l + mtspr SPRN_L1CSR1,r2 +1: + mfspr r3,SPRN_L1CSR1 + and. r1,r3,r2 + bne 1b + + lis r3,(L1CSR1_CPE|L1CSR1_ICE)@h + ori r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l + mtspr SPRN_L1CSR1,r3 isync - mtspr L1CSR1,r2 /* enable L1 Icache */ +2: + mfspr r3,SPRN_L1CSR1 + andi. r1,r3,L1CSR1_ICE@l + beq 2b + + /* Enable/invalidate the D-Cache */ + lis r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@h + ori r2,r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@l + mtspr SPRN_L1CSR0,r2 +1: + mfspr r3,SPRN_L1CSR0 + and. r1,r3,r2 + bne 1b + + lis r3,(L1CSR0_CPE|L1CSR0_DCE)@h + ori r3,r3,(L1CSR0_CPE|L1CSR0_DCE)@l + mtspr SPRN_L1CSR0,r3 isync - msync +2: + mfspr r3,SPRN_L1CSR0 + andi. r1,r3,L1CSR0_DCE@l + beq 2b /* Setup interrupt vectors */ lis r1,TEXT_BASE@h diff --git a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h index c6da411..9b3d616 100644 --- a/include/asm-ppc/processor.h +++ b/include/asm-ppc/processor.h @@ -485,10 +485,12 @@ #define SPRN_L2CFG0 0x207 /* L2 Cache Configuration Register 0 */ #define SPRN_L1CSR0 0x3f2 /* L1 Data Cache Control and Status Register 0 */ #define L1CSR0_CPE 0x00010000 /* Data Cache Parity Enable */ +#define L1CSR0_DCLFR 0x00000100 /* D-Cache Lock Flash Reset */ #define L1CSR0_DCFI 0x00000002 /* Data Cache Flash Invalidate */ #define L1CSR0_DCE 0x00000001 /* Data Cache Enable */ #define SPRN_L1CSR1 0x3f3 /* L1 Instruction Cache Control and Status Register 1 */ #define L1CSR1_CPE 0x00010000 /* Instruction Cache Parity Enable */ +#define L1CSR1_ICLFR 0x00000100 /* I-Cache Lock Flash Reset */ #define L1CSR1_ICFI 0x00000002 /* Instruction Cache Flash Invalidate */ #define L1CSR1_ICE 0x00000001 /* Instruction Cache Enable */ #define SPRN_L1CSR2 0x25e /* L1 Data Cache Control and Status Register 2 */ From 9ff32d8ccf0e23b5577c25610f001af8d761b4a2 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Mon, 29 Mar 2010 12:51:07 -0500 Subject: [PATCH 2/2] mpc86xx: set the DDR BATs after calculating true DDR size After determining how much DDR is actually in the system, set DBAT0 and IBAT0 accordingly. This ensures that the CPU won't attempt to access (via speculation) addresses outside of actual memory. On 86xx systems, DBAT0 and IBAT0 (the BATs for DDR) are initialized to 2GB and kept that way. If the system has less than 2GB of memory (typical for an MPC8610 HPCD), the CPU may attempt to access this memory during speculation. The zlib code is notorious for generating such memory reads, and indeed on the MPC8610, uncompressing the Linux kernel causes a machine check (without this patch). Currently we are limited to power of two sized DDR since we only use a single bat. If a non-power of two size is used that is less than CONFIG_MAX_MEM_MAPPED u-boot will crash. Signed-off-by: Timur Tabi Signed-off-by: Kumar Gala --- board/freescale/mpc8610hpcd/mpc8610hpcd.c | 2 ++ board/freescale/mpc8641hpcn/mpc8641hpcn.c | 2 ++ cpu/mpc86xx/cpu.c | 36 ++++++++++++++++++++++++++++++- cpu/mpc86xx/cpu_init.c | 4 ++++ include/asm-ppc/mmu.h | 6 +++++- include/configs/MPC8610HPCD.h | 6 ++---- include/configs/MPC8641HPCN.h | 4 +--- include/mpc86xx.h | 2 ++ 8 files changed, 53 insertions(+), 9 deletions(-) diff --git a/board/freescale/mpc8610hpcd/mpc8610hpcd.c b/board/freescale/mpc8610hpcd/mpc8610hpcd.c index 784a2ed..ab5f800 100644 --- a/board/freescale/mpc8610hpcd/mpc8610hpcd.c +++ b/board/freescale/mpc8610hpcd/mpc8610hpcd.c @@ -127,6 +127,8 @@ initdram(int board_type) dram_size = fixed_sdram(); #endif + setup_ddr_bat(dram_size); + puts(" DDR: "); return dram_size; } diff --git a/board/freescale/mpc8641hpcn/mpc8641hpcn.c b/board/freescale/mpc8641hpcn/mpc8641hpcn.c index c521527..443c9fd 100644 --- a/board/freescale/mpc8641hpcn/mpc8641hpcn.c +++ b/board/freescale/mpc8641hpcn/mpc8641hpcn.c @@ -74,6 +74,8 @@ initdram(int board_type) dram_size = fixed_sdram(); #endif + setup_ddr_bat(dram_size); + puts(" DDR: "); return dram_size; } diff --git a/cpu/mpc86xx/cpu.c b/cpu/mpc86xx/cpu.c index f7e012d..1887575 100644 --- a/cpu/mpc86xx/cpu.c +++ b/cpu/mpc86xx/cpu.c @@ -1,5 +1,5 @@ /* - * Copyright 2006,2009 Freescale Semiconductor, Inc. + * Copyright 2006,2009-2010 Freescale Semiconductor, Inc. * Jeff Brown * Srikanth Srinivasan (srikanth.srinivasan@freescale.com) * @@ -197,3 +197,37 @@ void mpc86xx_reginfo(void) printf("\tBR7\t0x%08X\tOR7\t0x%08X \n", in_be32(&lbc->br7), in_be32(&lbc->or7)); } + +/* + * Set the DDR BATs to reflect the actual size of DDR. + * + * dram_size is the actual size of DDR, in bytes + * + * Note: we assume that CONFIG_MAX_MEM_MAPPED is 2G or smaller as we only + * are using a single BAT to cover DDR. + * + * If this is not true, (e.g. CONFIG_MAX_MEM_MAPPED is 2GB but HID0_XBSEN + * is not defined) then we might have a situation where U-Boot will attempt + * to relocated itself outside of the region mapped by DBAT0. + * This will cause a machine check. + * + * Currently we are limited to power of two sized DDR since we only use a + * single bat. If a non-power of two size is used that is less than + * CONFIG_MAX_MEM_MAPPED u-boot will crash. + * + */ +void setup_ddr_bat(phys_addr_t dram_size) +{ + unsigned long batu, bl; + + bl = TO_BATU_BL(min(dram_size, CONFIG_MAX_MEM_MAPPED)); + + if (BATU_SIZE(bl) != dram_size) { + u64 sz = (u64)dram_size - BATU_SIZE(bl); + print_size(sz, " left unmapped\n"); + } + + batu = bl | BATU_VS | BATU_VP; + write_bat(DBAT0, batu, CONFIG_SYS_DBAT0L); + write_bat(IBAT0, batu, CONFIG_SYS_IBAT0L); +} diff --git a/cpu/mpc86xx/cpu_init.c b/cpu/mpc86xx/cpu_init.c index 5a78a9c..b4f047d 100644 --- a/cpu/mpc86xx/cpu_init.c +++ b/cpu/mpc86xx/cpu_init.c @@ -138,8 +138,12 @@ int cpu_init_r(void) /* Set up BAT registers */ void setup_bats(void) { +#if defined(CONFIG_SYS_DBAT0U) && defined(CONFIG_SYS_DBAT0L) write_bat(DBAT0, CONFIG_SYS_DBAT0U, CONFIG_SYS_DBAT0L); +#endif +#if defined(CONFIG_SYS_IBAT0U) && defined(CONFIG_SYS_IBAT0L) write_bat(IBAT0, CONFIG_SYS_IBAT0U, CONFIG_SYS_IBAT0L); +#endif write_bat(DBAT1, CONFIG_SYS_DBAT1U, CONFIG_SYS_DBAT1L); write_bat(IBAT1, CONFIG_SYS_IBAT1U, CONFIG_SYS_IBAT1L); write_bat(DBAT2, CONFIG_SYS_DBAT2U, CONFIG_SYS_DBAT2L); diff --git a/include/asm-ppc/mmu.h b/include/asm-ppc/mmu.h index fd10249..ce7f081 100644 --- a/include/asm-ppc/mmu.h +++ b/include/asm-ppc/mmu.h @@ -213,7 +213,11 @@ extern void print_bats(void); #define BATL_PADDR(x) ((phys_addr_t)((x & 0xfffe0000) \ | ((x & 0x0e00ULL) << 24) \ | ((x & 0x04ULL) << 30))) -#define BATU_SIZE(x) (1UL << (fls((x & BATU_BL_MAX) >> 2) + 17)) +#define BATU_SIZE(x) (1ULL << (fls((x & BATU_BL_MAX) >> 2) + 17)) + +/* bytes into BATU_BL */ +#define TO_BATU_BL(x) \ + (u32)((((1ull << __ilog2_u64((u64)x)) / (128 * 1024)) - 1) * 4) /* Used to set up SDR1 register */ #define HASH_TABLE_SIZE_64K 0x00010000 diff --git a/include/configs/MPC8610HPCD.h b/include/configs/MPC8610HPCD.h index 1d2d659..fed441e 100644 --- a/include/configs/MPC8610HPCD.h +++ b/include/configs/MPC8610HPCD.h @@ -341,10 +341,8 @@ * BAT0 2G Cacheable, non-guarded * 0x0000_0000 2G DDR */ -#define CONFIG_SYS_DBAT0L (BATL_PP_RW | BATL_MEMCOHERENCE) -#define CONFIG_SYS_DBAT0U (BATU_BL_2G | BATU_VS | BATU_VP) -#define CONFIG_SYS_IBAT0L (BATL_PP_RW | BATL_MEMCOHERENCE ) -#define CONFIG_SYS_IBAT0U CONFIG_SYS_DBAT0U +#define CONFIG_SYS_DBAT0L (BATL_PP_RW) +#define CONFIG_SYS_IBAT0L (BATL_PP_RW) /* * BAT1 1G Cache-inhibited, guarded diff --git a/include/configs/MPC8641HPCN.h b/include/configs/MPC8641HPCN.h index 12a8f60..94e4d24 100644 --- a/include/configs/MPC8641HPCN.h +++ b/include/configs/MPC8641HPCN.h @@ -482,9 +482,7 @@ extern unsigned long get_board_sys_clk(unsigned long dummy); * BAT0 DDR */ #define CONFIG_SYS_DBAT0L (BATL_PP_RW | BATL_MEMCOHERENCE) -#define CONFIG_SYS_DBAT0U (BATU_BL_2G | BATU_VS | BATU_VP) -#define CONFIG_SYS_IBAT0L (BATL_PP_RW | BATL_MEMCOHERENCE ) -#define CONFIG_SYS_IBAT0U CONFIG_SYS_DBAT0U +#define CONFIG_SYS_IBAT0L (BATL_PP_RW | BATL_MEMCOHERENCE) /* * BAT1 LBC (PIXIS/CF) diff --git a/include/mpc86xx.h b/include/mpc86xx.h index c6f30f9..eb85d60 100644 --- a/include/mpc86xx.h +++ b/include/mpc86xx.h @@ -83,5 +83,7 @@ static __inline__ unsigned long get_l2cr (void) return l2cr_val; } +void setup_ddr_bat(phys_addr_t dram_size); + #endif /* _ASMLANGUAGE */ #endif /* __MPC86xx_H__ */