[coreboot] New patch to review for coreboot: 8df71ac armv7/exynos/snow: set up caches properly

David Hendricks (dhendrix@chromium.org) gerrit at coreboot.org
Fri Mar 15 04:50:54 CET 2013


David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2729

-gerrit

commit 8df71ac74d177e1e0138a86310a2f5240fa27c25
Author: David Hendricks <dhendrix at 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 at 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();



More information about the coreboot mailing list