David Hendricks (dhendrix@chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2729
-gerrit
commit 5748b462f1c22cd5ba41d8c09563fa2d872ef909 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: - Get rid of imported CP15ISB and isb() macros. They are wrong for ARMv7 -- it was assumed in u-boot that the code would be compiled with -march=armv5 (see comment in armv7.h). - Clean up. Most of this is now done in a generic manner in bootblock_simple, so a lot of earlier code can go away. - Set cache policy explicitly before re-enabling - Replace imported cache routines (and use BSD license to match libpayload?)
Change-Id: I7390981190e3213f4e1431f8e56746545c5cc7c9 Signed-off-by: David Hendricks dhendrix@chromium.org --- src/arch/armv7/bootblock_simple.c | 71 +++++++++++++++++++++++++++++++ src/arch/armv7/include/arch/io.h | 3 +- src/arch/armv7/include/cache.h | 56 ------------------------ src/arch/armv7/include/system.h | 8 +++- src/arch/armv7/lib/Makefile.inc | 6 +++ 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 | 2 + src/cpu/samsung/exynos5250/exynos_cache.c | 8 +--- src/mainboard/google/snow/ramstage.c | 15 ------- src/mainboard/google/snow/romstage.c | 37 +++++----------- 12 files changed, 101 insertions(+), 111 deletions(-)
diff --git a/src/arch/armv7/bootblock_simple.c b/src/arch/armv7/bootblock_simple.c index 0132b87..7012e17 100644 --- a/src/arch/armv7/bootblock_simple.c +++ b/src/arch/armv7/bootblock_simple.c @@ -20,6 +20,7 @@ */
#include <bootblock_common.h> +#include <arch/cache.h> #include <arch/hlt.h> #include <arch/stages.h> #include <cbfs.h> @@ -27,6 +28,58 @@
#include "stages.c"
+static void armv7_invalidate_caches(void) +{ + uint32_t clidr; + int level; + + /* Invalidate branch predictor */ + bpiall(); + + /* Iterate thru each cache identified in CLIDR and invalidate */ + clidr = read_clidr(); + for (level = 0; level < 7; level++) { + unsigned int ctype = (clidr >> (level * 3)) & 0x7; + uint32_t csselr; + + switch(ctype) { + case 0x0: + /* no cache */ + break; + case 0x1: + /* icache only */ + csselr = (level << 1) | 1; + write_csselr(csselr); + icache_invalidate_all(); + break; + case 0x2: + case 0x4: + /* dcache only or unified cache */ + dcache_invalidate_all(); + break; + case 0x3: + /* separate icache and dcache */ + csselr = (level << 1) | 1; + write_csselr(csselr); + icache_invalidate_all(); + + csselr = level < 1; + write_csselr(csselr); + dcache_invalidate_all(); + break; + default: + /* reserved */ + break; + } + } + + /* Invalidate TLB */ + /* FIXME: ARMv7 Architecture Ref. Manual claims that the distinction + * instruction vs. data TLBs is deprecated in ARMv7. But that doesn't + * really seem true for Cortex-A15? */ + tlb_invalidate_all(); +} + static int boot_cpu(void) { /* @@ -41,6 +94,24 @@ void main(void) { const char *stage_name = "fallback/romstage"; void *entry; + uint32_t sctlr; + + /* Globally disable MMU, caches, and branch prediction (these should + * be disabled by default on reset) */ + sctlr = read_sctlr(); + sctlr &= ~(SCTLR_M | SCTLR_C | SCTLR_Z | SCTLR_I); + write_sctlr(sctlr); + + armv7_invalidate_caches(); + + /* + * Re-enable caches and branch prediction. MMU will be set up later. + * Note: If booting from USB, we need to disable branch prediction + * before copying from USB into RAM (FIXME: why?) + */ + sctlr = read_sctlr(); + sctlr |= SCTLR_C | SCTLR_Z | SCTLR_I; + write_sctlr(sctlr);
if (boot_cpu()) { bootblock_cpu_init(); diff --git a/src/arch/armv7/include/arch/io.h b/src/arch/armv7/include/arch/io.h index 3bbd529..623c305 100644 --- a/src/arch/armv7/include/arch/io.h +++ b/src/arch/armv7/include/arch/io.h @@ -21,6 +21,7 @@ #define __ASM_ARM_IO_H
#include <types.h> +#include <arch/cache.h> /* for dmb() */ #include <arch/byteorder.h>
static inline void sync(void) @@ -96,7 +97,7 @@ extern inline void __raw_readsl(unsigned int addr, void *data, int longlen) * TODO: The kernel offers some more advanced versions of barriers, it might * have some advantages to use them instead of the simple one here. */ -#define dmb() __asm__ __volatile__ ("" : : : "memory") +//#define dmb() __asm__ __volatile__ ("" : : : "memory") #define __iormb() dmb() #define __iowmb() dmb()
diff --git a/src/arch/armv7/include/cache.h b/src/arch/armv7/include/cache.h deleted file mode 100644 index cf8fb5a..0000000 --- a/src/arch/armv7/include/cache.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * (C) Copyright 2009 - * Marvell Semiconductor <www.marvell.com> - * Written-by: Prafulla Wadaskar prafulla@marvell.com - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - */ - -#ifndef _ASM_CACHE_H -#define _ASM_CACHE_H - -/* - * Invalidate L2 Cache using co-proc instruction - */ -static inline void invalidate_l2_cache(void) -{ - unsigned int val=0; - - asm volatile("mcr p15, 1, %0, c15, c11, 0 @ invl l2 cache" - : : "r" (val) : "cc"); - isb(); -} - -void l2_cache_enable(void); -void l2_cache_disable(void); - -/* - * The current upper bound for ARM L1 data cache line sizes is 64 bytes. We - * use that value for aligning DMA buffers unless the board config has specified - * an alternate cache line size. - */ -#ifdef CONFIG_SYS_CACHELINE_SIZE -#define ARCH_DMA_MINALIGN CONFIG_SYS_CACHELINE_SIZE -#else -#define ARCH_DMA_MINALIGN 64 -#endif - -inline void dram_bank_mmu_setup(unsigned long start, unsigned long size); - -#endif /* _ASM_CACHE_H */ diff --git a/src/arch/armv7/include/system.h b/src/arch/armv7/include/system.h index 053df8d..d4e778d 100644 --- a/src/arch/armv7/include/system.h +++ b/src/arch/armv7/include/system.h @@ -43,13 +43,15 @@ */ #define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t"
-#define isb() __asm__ __volatile__ ("" : : : "memory") +/* FIXME: conflicts with new implementation in cache.c */ +//#define isb() __asm__ __volatile__ ("" : : : "memory")
#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
#define arch_align_stack(x) (x)
#ifndef __ASSEMBLER__ +#include <arch/cache.h> /* for isb() */ static inline unsigned int get_cr(void) { unsigned int val; @@ -61,7 +63,7 @@ static inline void set_cr(unsigned int val) { asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR" : : "r" (val) : "cc"); - isb(); + isb(); /* ref: B3.10.2 of ARM Arch Ref. Manual for ARMv7 */ }
/* options available for data cache on each page */ @@ -97,6 +99,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..0741afa 100644 --- a/src/arch/armv7/lib/Makefile.inc +++ b/src/arch/armv7/lib/Makefile.inc @@ -1,8 +1,12 @@ +#FIXME: cache_v7 and cache-cp15 will go away eventually + bootblock-y += syslib.c bootblock-$(CONFIG_EARLY_CONSOLE) += early_console.c +bootblock-y += cache.c bootblock-y += cache_v7.c bootblock-y += cache-cp15.c
+romstage-y += cache.c romstage-y += cache_v7.c romstage-y += cache-cp15.c romstage-y += div0.c @@ -14,6 +18,8 @@ ramstage-y += div0.c #ramstage-y += memcpy.S #ramstage-y += memset.S ramstage-y += syslib.c +ramstage-y += cache.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..4995dc2 100644 --- a/src/cpu/samsung/exynos5250/bootblock.c +++ b/src/cpu/samsung/exynos5250/bootblock.c @@ -17,6 +17,8 @@ * 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) { 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/ramstage.c b/src/mainboard/google/snow/ramstage.c index e4d53cf..687f9b1 100644 --- a/src/mainboard/google/snow/ramstage.c +++ b/src/mainboard/google/snow/ramstage.c @@ -23,22 +23,10 @@ #include <cpu/samsung/exynos5250/clk.h> #include <cpu/samsung/exynos5250/power.h>
-#include <system.h> /* FIXME: for testing cache */ -static void cp_delay(void) -{ - volatile int i; - - /* copro seems to need some delay between reading and writing */ - for (i = 0; i < 100; i++) - nop(); - asm volatile("" : : : "memory"); -} - static inline uint32_t read_clidr(void) { uint32_t val = 0; asm volatile ("mrc p15, 1, %0, c0, c0, 1" : "=r" (val)); - isb(); return val; }
@@ -46,7 +34,6 @@ static inline uint32_t read_ccsidr(void) { uint32_t val = 0; asm volatile ("mrc p15, 1, %0, c0, c0, 0" : "=r" (val)); - isb(); return val; }
@@ -54,7 +41,6 @@ static inline uint32_t read_csselr(void) { uint32_t val = 0; asm volatile ("mrc p15, 2, %0, c0, c0, 0" : "=r" (val)); - isb(); return val; }
@@ -66,7 +52,6 @@ static inline void write_csselr(uint32_t val) * Bit 0 - 0 = data or unified cache, 1 = instruction cache */ asm volatile ("mcr p15, 2, %0, c0, c0, 0" : : "r" (val)); - isb(); }
#ifndef __mask diff --git a/src/mainboard/google/snow/romstage.c b/src/mainboard/google/snow/romstage.c index ea2feec..c90be6e 100644 --- a/src/mainboard/google/snow/romstage.c +++ b/src/mainboard/google/snow/romstage.c @@ -18,12 +18,12 @@ */
#include <types.h> -#include <system.h>
-#include <cache.h> +#include <armv7.h> #include <cbfs.h> #include <common.h>
+#include <arch/cache.h> #include <arch/gpio.h> #include <cpu/samsung/exynos5250/clk.h> #include <cpu/samsung/exynos5250/dmc.h> @@ -52,20 +52,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. */ @@ -95,12 +81,14 @@ void main(void) 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); - 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 +97,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,7 +114,8 @@ void main(void) while(1); }
- mmu_setup(CONFIG_SYS_SDRAM_BASE, CONFIG_DRAM_SIZE_MB); + /* Set up MMU and caches */ + mmu_setup_by_mva(CONFIG_SYS_SDRAM_BASE, CONFIG_DRAM_SIZE_MB);
initialize_s5p_mshc();