[U-Boot] [PATCH 3/8] armv7: integrate cache maintenance support

Aneesh V
2010-12-22T11:54:53Z

- Enable I-cache on bootup
- Enable MMU and D-cache immediately after relocation
- Do necessary initialization before enabling d-cache and MMU
- Changes to cleanup_before_linux()
- Make changes according to the new framework

Signed-off-by: Aneesh V <aneesh@ti.com>
---
arch/arm/cpu/armv7/cpu.c | 47 +++++++++++++++++++------------------------
arch/arm/cpu/armv7/start.S | 18 +++++++++++++++-
arch/arm/lib/board.c | 6 +++++
arch/arm/lib/cache-cp15.c | 9 ++++++++
4 files changed, 53 insertions(+), 27 deletions(-)

diff --git a/arch/arm/cpu/armv7/cpu.c b/arch/arm/cpu/armv7/cpu.c
index a01e0d6..b418304 100644
--- a/arch/arm/cpu/armv7/cpu.c
+++ b/arch/arm/cpu/armv7/cpu.c
@@ -38,13 +38,10 @@
#ifndef CONFIG_L2_OFF
#include <asm/arch/sys_proto.h>
#endif
-
-static void cache_flush(void);
+#include <asm/armv7.h>

int cleanup_before_linux(void)
{
- unsigned int i;
-
/*
* this function is called just before we call linux
* it prepares the processor for linux
@@ -53,31 +50,29 @@ int cleanup_before_linux(void)
*/
disable_interrupts();

- /* turn off I/D-cache */
+ /*
+ * Turn off I-cache and invalidate it
+ */
icache_disable();
- dcache_disable();
+ invalidate_icache_all();

- /* invalidate I-cache */
- cache_flush();
-
-#ifndef CONFIG_L2_OFF
- /* turn off L2 cache */
- l2_cache_disable();
- /* invalidate L2 cache also */
- invalidate_dcache(get_device_type());
-#endif
- i = 0;
- /* mem barrier to sync up things */
- asm("mcr p15, 0, %0, c7, c10, 4": :"r"(i));
+ /*
+ * turn off D-cache
+ * dcache_disable() in turn flushes the d-cache and disables MMU
+ */
+ dcache_disable();

-#ifndef CONFIG_L2_OFF
- l2_cache_enable();
-#endif
+ /*
+ * After D-cache is flushed and before it is disabled there may
+ * be some new valid entries brought into the cache. We are sure
+ * that these lines are not dirty and will not affect our execution.
+ * (because unwinding the call-stack and setting a bit in CP15 SCTRL
+ * is all we did during this. We have not pushed anything on to the
+ * stack. Neither have we affected any static data)
+ * So just invalidate the entire d-cache again to avoid coherency
+ * problems for kernel
+ */
+ invalidate_dcache_all();

return 0;
}
-
-static void cache_flush(void)
-{
- asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0));
-}
diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S
index 684f2d2..7d17f1e 100644
--- a/arch/arm/cpu/armv7/start.S
+++ b/arch/arm/cpu/armv7/start.S
@@ -241,6 +241,14 @@ clbss_l:str r2, [r0] /* clear loop... */
* initialization, now running from RAM.
*/
jump_2_ram:
+/*
+ * If I-cache is enabled invalidate it
+ */
+#ifndef CONFIG_SYS_NO_ICACHE
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
+ dsb
+ isb
+#endif
ldr r0, _board_init_r_ofs
adr r1, _start
add lr, r0, r1
@@ -276,6 +284,9 @@ cpu_init_crit:
mov r0, #0 @ set up for MCR
mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
+ mcr p15, 0, r0, c7, c5, 6 /* invalidate BP array */
+ dsb
+ isb

/*
* disable MMU stuff and caches
@@ -284,7 +295,12 @@ cpu_init_crit:
bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
- orr r0, r0, #0x00000800 @ set bit 12 (Z---) BTB
+ orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
+#ifdef CONFIG_SYS_NO_ICACHE
+ bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache
+#else
+ orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache
+#endif
mcr p15, 0, r0, c1, c0, 0

/*
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
index 7266381..bef32a6 100644
--- a/arch/arm/lib/board.c
+++ b/arch/arm/lib/board.c
@@ -459,6 +459,12 @@ void board_init_r (gd_t *id, ulong dest_addr)

gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */

+ /*
+ * Enable D$:
+ * I$, if needed, must be already enabled in start.S
+ */
+ dcache_enable();
+
monitor_flash_len = _bss_start_ofs;
debug ("monitor flash len: %08lX\n", monitor_flash_len);
board_init(); /* Setup chipselects */
diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c
index d9175f0..ca526fb 100644
--- a/arch/arm/lib/cache-cp15.c
+++ b/arch/arm/lib/cache-cp15.c
@@ -34,6 +34,14 @@

DECLARE_GLOBAL_DATA_PTR;

+void __arm_init_before_mmu(void)
+{
+ puts("__arm_init_before_mmu: dummy implementation! "
+ "real implementation missing!!\n");
+}
+void arm_init_before_mmu(void)
+ __attribute__((weak, alias("__arm_init_before_mmu")));
+
static void cp_delay (void)
{
volatile int i;
@@ -65,6 +73,7 @@ static inline void mmu_setup(void)
int i;
u32 reg;

+ arm_init_before_mmu();
/* Set up an identity-mapping for all 4GB, rw for everyone */
for (i = 0; i < 4096; i++)
page_table[i] = i << 20 | (3 << 10) | 0x12;
--
1.7.0.4