Stefan Reinauer (stefan.reinauer@coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2729
-gerrit
commit 29d9d6c682d651b470a67f8d04dc3948c0f5d955 Author: David Hendricks dhendrix@chromium.org Date: Thu Mar 14 15:24:57 2013 -0700
armv7/exynos/snow: set up caches properly
** do not submit **
This (hopefully) sets up caches more carefully than we were doing before. This patch needs a bit more testing before going in.
TODO: Code placement needs to be tidied up. Right now the code is scattered about in a less-than-ideal manner due to the differences between handling L1 cache (generic for ARMv7) and L2 (SoC-dependent). I suspect we'll disable and invalidate L1 in the CPU bootblock, then do try to consolidate everything else in a helper function called from the board's romstage (since we need board DRAM info for MMU setup).
Change-Id: I7390981190e3213f4e1431f8e56746545c5cc7c9 Signed-off-by: David Hendricks dhendrix@chromium.org --- src/arch/armv7/bootblock_simple.c | 57 +++++++++++++++++++++++++++++++ src/arch/armv7/include/system.h | 16 +++++++++ src/arch/armv7/lib/Makefile.inc | 1 + src/arch/armv7/lib/cache-cp15.c | 3 +- src/arch/armv7/lib/cache_v7.c | 2 +- src/cpu/samsung/exynos5250/Makefile.inc | 1 - src/cpu/samsung/exynos5250/bootblock.c | 6 ++++ src/cpu/samsung/exynos5250/exynos_cache.c | 8 ++--- src/mainboard/google/snow/romstage.c | 45 ++++++++++++------------ 9 files changed, 105 insertions(+), 34 deletions(-)
diff --git a/src/arch/armv7/bootblock_simple.c b/src/arch/armv7/bootblock_simple.c index 0132b87..0b2d884 100644 --- a/src/arch/armv7/bootblock_simple.c +++ b/src/arch/armv7/bootblock_simple.c @@ -24,9 +24,57 @@ #include <arch/stages.h> #include <cbfs.h> #include <console/console.h> +#include <system.h>
#include "stages.c"
+/* + * Set/clear program flow prediction and return the previous state. + */ +static int config_branch_prediction(int set_cr_z) +{ + unsigned int cr; + + /* System Control Register: 11th bit Z Branch prediction enable */ + cr = get_cr(); + set_cr(set_cr_z ? cr | CR_Z : cr & ~CR_Z); + + return cr & CR_Z; +} + +/* Cache and MMU init */ +static void armv7_invalidate_caches(void) +{ + unsigned int cr; + + /* + * From Cortex-A Series Programmers guide (Example 15-3): + * 1. Disable MMU + * 2. Disable L1 caches (example disables i-cache then d-cache) + * 3. Invalidate L1 caches (same order) + * 4. Invalidate TLB + * + * L2 cache setup will be done by SoC-specific code. MMU setup + * needs to be done after DRAM init in board-specific code. + */ + + /* Disable MMU */ + cr = get_cr(); + cr &= ~CR_M; + set_cr(cr); + + /* Disable L1 caches */ + icache_disable(); + dcache_disable(); + + /* Invalidate caches */ + invalidate_icache_all(); + invalidate_dcache_all(); + + /* Invalidate TLB */ + v7_inval_tlb(); +} + static int boot_cpu(void) { /* @@ -42,6 +90,15 @@ void main(void) const char *stage_name = "fallback/romstage"; void *entry;
+ armv7_invalidate_caches(); + + /* + * Branch prediction enable. + * Note: If booting from USB, we need to disable branch prediction + * before copying from USB into RAM (FIXME: why?) + */ + config_branch_prediction(1); + if (boot_cpu()) { bootblock_cpu_init(); bootblock_mainboard_init(); diff --git a/src/arch/armv7/include/system.h b/src/arch/armv7/include/system.h index 053df8d..9a694ba 100644 --- a/src/arch/armv7/include/system.h +++ b/src/arch/armv7/include/system.h @@ -64,6 +64,20 @@ static inline void set_cr(unsigned int val) isb(); }
+static inline unsigned int get_acr(void) +{ + unsigned int val; + asm("mrc p15, 0, %0, c1, c0, 1 @ get ACR" : "=r" (val) : : "cc"); + return val; +} + +static inline void set_acr(unsigned int val) +{ + asm volatile("mcr p15, 0, %0, c1, c0, 1 @ set ACR" + : : "r" (val) : "cc"); + isb(); +} + /* options available for data cache on each page */ enum dcache_option { DCACHE_OFF, @@ -97,6 +111,8 @@ void mmu_page_table_flush(unsigned long start, unsigned long stop);
void mmu_setup(unsigned long start, unsigned long size);
+void v7_inval_tlb(void); + void arm_init_before_mmu(void);
/* diff --git a/src/arch/armv7/lib/Makefile.inc b/src/arch/armv7/lib/Makefile.inc index 508f776..75e6752 100644 --- a/src/arch/armv7/lib/Makefile.inc +++ b/src/arch/armv7/lib/Makefile.inc @@ -14,6 +14,7 @@ ramstage-y += div0.c #ramstage-y += memcpy.S #ramstage-y += memset.S ramstage-y += syslib.c +ramstage-y += cache-cp15.c ramstage-y += cache_v7.c
#FIXME(dhendrix): should this be a config option? diff --git a/src/arch/armv7/lib/cache-cp15.c b/src/arch/armv7/lib/cache-cp15.c index e08ea57..32f3c79 100644 --- a/src/arch/armv7/lib/cache-cp15.c +++ b/src/arch/armv7/lib/cache-cp15.c @@ -123,8 +123,7 @@ inline void mmu_setup(unsigned long start, unsigned long size_mb) int i; u32 reg;
- arm_init_before_mmu(); - +// arm_init_before_mmu(); /* Set up an identity-mapping for all 4GB, rw for everyone */ for (i = 0; i < 4096; i++) set_section_dcache(i, DCACHE_OFF); diff --git a/src/arch/armv7/lib/cache_v7.c b/src/arch/armv7/lib/cache_v7.c index 31072c7..1764351 100644 --- a/src/arch/armv7/lib/cache_v7.c +++ b/src/arch/armv7/lib/cache_v7.c @@ -226,7 +226,7 @@ static void v7_dcache_maint_range(u32 start, u32 stop, u32 range_op) }
/* Invalidate TLB */ -static void v7_inval_tlb(void) +void v7_inval_tlb(void) { /* Invalidate entire unified TLB */ asm volatile ("mcr p15, 0, %0, c8, c7, 0" : : "r" (0)); diff --git a/src/cpu/samsung/exynos5250/Makefile.inc b/src/cpu/samsung/exynos5250/Makefile.inc index 2774b12..961b719 100644 --- a/src/cpu/samsung/exynos5250/Makefile.inc +++ b/src/cpu/samsung/exynos5250/Makefile.inc @@ -30,7 +30,6 @@ ramstage-y += power.c ramstage-y += soc.c ramstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c ramstage-y += cpu.c -ramstage-y += exynos_cache.c
#ramstage-$(CONFIG_SATA_AHCI) += sata.c
diff --git a/src/cpu/samsung/exynos5250/bootblock.c b/src/cpu/samsung/exynos5250/bootblock.c index 949468f..48f390a 100644 --- a/src/cpu/samsung/exynos5250/bootblock.c +++ b/src/cpu/samsung/exynos5250/bootblock.c @@ -17,7 +17,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <armv7.h> + void bootblock_cpu_init(void); void bootblock_cpu_init(void) { + /* Enable L2 cache */ + /* FIXME: maybe do this in romstage along with the other cache + * init functions? */ + v7_outer_cache_enable(); } diff --git a/src/cpu/samsung/exynos5250/exynos_cache.c b/src/cpu/samsung/exynos5250/exynos_cache.c index 7f4effe..87eded5 100644 --- a/src/cpu/samsung/exynos5250/exynos_cache.c +++ b/src/cpu/samsung/exynos5250/exynos_cache.c @@ -34,15 +34,11 @@ enum l2_cache_params { };
-/* FIXME(dhendrix): maybe move this to a romstage-specific file? */ -#ifdef __PRE_RAM__ void enable_caches(void) { - /* Enable D-cache. I-cache is already enabled in start.S */ - /* can't use it anyway -- it has dependencies we have to fix. */ - //dcache_enable(); + icache_enable(CONFIG_SYS_SDRAM_BASE, CONFIG_DRAM_SIZE_MB); + dcache_enable(CONFIG_SYS_SDRAM_BASE, CONFIG_DRAM_SIZE_MB); } -#endif
/* * Set L2 cache parameters diff --git a/src/mainboard/google/snow/romstage.c b/src/mainboard/google/snow/romstage.c index ea2feec..3b14d91 100644 --- a/src/mainboard/google/snow/romstage.c +++ b/src/mainboard/google/snow/romstage.c @@ -20,6 +20,7 @@ #include <types.h> #include <system.h>
+#include <armv7.h> #include <cache.h> #include <cbfs.h> #include <common.h> @@ -52,20 +53,6 @@ static int board_wakeup_permitted(void) } #endif
-/* - * Set/clear program flow prediction and return the previous state. - */ -static int config_branch_prediction(int set_cr_z) -{ - unsigned int cr; - - /* System Control Register: 11th bit Z Branch prediction enable */ - cr = get_cr(); - set_cr(set_cr_z ? cr | CR_Z : cr & ~CR_Z); - - return cr & CR_Z; -} - static void initialize_s5p_mshc(void) { /* MMC0: Fixed, 8 bit mode, connected with GPIO. */ @@ -94,13 +81,16 @@ void main(void) struct arm_clk_ratios *arm_ratios; int ret; void *entry; - - /* FIXME: if we boot from USB, we need to disable branch prediction - * before copying from USB into RAM */ - config_branch_prediction(1); + unsigned int cr;
clock_set_rate(PERIPH_ID_SPI1, 50000000); /* set spi clock to 50Mhz */
+ /* + * FIXME: Do necessary I2C init so low-level PMIC code doesn't need to. + * Also, we should only call power_init() on cold boot. + */ + power_init(); + /* Clock must be initialized before console_init, otherwise you may need * to re-initialize serial console drivers again. */ mem = get_mem_timings(); @@ -109,12 +99,6 @@ void main(void)
console_init();
- /* - * FIXME: Do necessary I2C init so low-level PMIC code doesn't need to. - * Also, we should only call power_init() on cold boot. - */ - power_init(); - if (!mem) { printk(BIOS_CRIT, "Unable to auto-detect memory timings\n"); while(1); @@ -132,8 +116,21 @@ void main(void) while(1); }
+ /* Set up MMU and caches */ mmu_setup(CONFIG_SYS_SDRAM_BASE, CONFIG_DRAM_SIZE_MB);
+ /* Enable D-side prefetch */ + cr = get_acr(); + cr |= (1 << 2); + set_acr(cr); + CP15DSB; + CP15ISB; + + /* FIXME: these functions take because the "generic" cache_enable() + * tries to call mmu_setup if mmu has not already been enabled */ + icache_enable(CONFIG_SYS_SDRAM_BASE, CONFIG_DRAM_SIZE_MB); + dcache_enable(CONFIG_SYS_SDRAM_BASE, CONFIG_DRAM_SIZE_MB); + initialize_s5p_mshc();
graphics();