[U-Boot] [PATCH 2/6] SH2A cache support.

Yoshinori Sato ysato at users.sourceforge.jp
Tue Feb 11 13:24:42 CET 2014


Signed-off-by: Yoshinori Sato <ysato at users.sourceforge.jp>
---
 arch/sh/cpu/sh2/Makefile      |   6 ++
 arch/sh/cpu/sh2/cache-sh2a.c  | 143 ++++++++++++++++++++++++++++++++++++++++++
 arch/sh/cpu/sh2/cpu.c         |  31 ---------
 arch/sh/cpu/sh2/nocache.c     |  37 +++++++++++
 arch/sh/include/asm/cpu_sh2.h |   9 ---
 5 files changed, 186 insertions(+), 40 deletions(-)
 create mode 100644 arch/sh/cpu/sh2/cache-sh2a.c
 create mode 100644 arch/sh/cpu/sh2/nocache.c

diff --git a/arch/sh/cpu/sh2/Makefile b/arch/sh/cpu/sh2/Makefile
index a19ed5e..6a11448 100644
--- a/arch/sh/cpu/sh2/Makefile
+++ b/arch/sh/cpu/sh2/Makefile
@@ -4,9 +4,15 @@
 #
 # Copyright (C) 2007,2008 Nobuhiro Iwamatsu <iwamatsu at nigauri.org>
 # Copyright (C) 2008 Renesas Solutions Corp.
+# Copyright (C) 2013 Yoshinori Sato <ysato at users.sourceforge.jp>
 #
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
 extra-y	= start.o
 obj-y	= cpu.o interrupts.o watchdog.o
+ifdef CONFIG_SH2A
+obj-y	+= cache-sh2a.o
+else
+obj-y	+= nocache.o
+endif
diff --git a/arch/sh/cpu/sh2/cache-sh2a.c b/arch/sh/cpu/sh2/cache-sh2a.c
new file mode 100644
index 0000000..a7bf5bc
--- /dev/null
+++ b/arch/sh/cpu/sh2/cache-sh2a.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2013 Yoshinori Sato <ysato at users.sourceforge.jp>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+/*
+ * Jump to cache disabled area
+ * When handling caches, we need to do it from non-cache area.
+ */
+#define jump_to_uncacheable()			\
+do {					\
+	unsigned long __dummy;		\
+	__asm__ __volatile__(		\
+		"mov.l  1f, %0\n\t"	\
+		"or     %1, %0\n\t"	\
+		"jmp    @%0\n\t"	\
+		" nop\n\t"		\
+		".balign 4\n"		\
+		"1:     .long 2f\n"	\
+		"2:"			\
+		: "=&r" (__dummy)	\
+		: "r" (0x20000000));	\
+} while (0)
+
+/*
+ * Back to cache area.
+ */
+#define back_to_cacheable()			\
+do {					\
+	unsigned long __dummy;		\
+	__asm__ __volatile__(		\
+		"nop;nop;nop;nop;nop;nop;nop\n\t"	\
+		"mov.l  1f, %0\n\t"	\
+		"jmp    @%0\n\t"	\
+		" nop\n\t"		\
+		".balign 4\n"		\
+		"1:     .long 2f\n"	\
+		"2:"			\
+		: "=&r" (__dummy));	\
+} while (0)
+
+#define CACHE_OC_NUM_ENTRIES 128
+#define CACHE_OC_NUM_WAYS 4
+#define CACHE_OC_ADDRESS_ARRAY 0xf0800000
+#define CACHE_OC_WAY_SHIFT 11
+#define CACHE_OC_ENTRY_SHIFT 2
+#define CACHE_UPDATED 0x02
+
+static inline void cache_wback_all(void)
+{
+	unsigned long addr, data, i, j;
+
+	for (i = 0; i < CACHE_OC_NUM_ENTRIES; i++){
+		for (j = 0; j < CACHE_OC_NUM_WAYS; j++) {
+			addr = CACHE_OC_ADDRESS_ARRAY | (j << CACHE_OC_WAY_SHIFT)
+				| (i << CACHE_OC_ENTRY_SHIFT);
+			data = inl(addr);
+			if (data & CACHE_UPDATED) {
+				data &= ~CACHE_UPDATED;
+				outl(data, addr);
+			}
+		}
+	}
+}
+void flush_cache(unsigned long addr, unsigned long size)
+{
+	unsigned long entry;
+	unsigned long tag;
+	size = (size + 3) & ~3;
+	jump_to_uncacheable();
+	while(size > 0) {
+		entry = addr & 0x000003ff0;
+		tag = addr & 0x1ffff0000;
+		/* I-Cache flush */
+		outl(tag, 0xf0000008 | entry);
+		/* D-Cache flush with wb */
+		outl(tag, 0xf0800008 | entry);
+		addr += 4;
+		size -= 4;
+	}
+	back_to_cacheable();
+}
+
+void icache_enable(void)
+{
+	unsigned long ccr;
+	ccr = readl(CCR1);
+	ccr |= 0x00000900;
+	jump_to_uncacheable();
+	writel(ccr, CCR1);
+	back_to_cacheable();
+}
+
+void icache_disable(void)
+{
+	unsigned long ccr;
+	ccr = readl(CCR1);
+	ccr &= ~0x00000100;
+	jump_to_uncacheable();
+	writel(ccr, CCR1);
+	back_to_cacheable();
+}
+
+int icache_status(void)
+{
+	unsigned long ccr;
+	ccr = readl(CCR1);
+	return ((ccr & 0x00000100) != 0);
+}
+
+void dcache_enable(void)
+{
+	unsigned long ccr;
+	ccr = readl(CCR1);
+	ccr |= 0x00000009;
+	jump_to_uncacheable();
+	writel(ccr, CCR1);
+	back_to_cacheable();
+}
+
+void dcache_disable(void)
+{
+	unsigned long ccr;
+	ccr = readl(CCR1);
+	ccr &= ~0x00000001;
+	jump_to_uncacheable();
+	cache_wback_all();
+	writel(ccr, CCR1);
+	back_to_cacheable();
+}
+
+int dcache_status(void)
+{
+	unsigned long ccr;
+	ccr = readl(CCR1);
+	return ((ccr & 0x00000001) != 0);
+}
diff --git a/arch/sh/cpu/sh2/cpu.c b/arch/sh/cpu/sh2/cpu.c
index a2f856f..b401d08 100644
--- a/arch/sh/cpu/sh2/cpu.c
+++ b/arch/sh/cpu/sh2/cpu.c
@@ -52,34 +52,3 @@ int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	reset_cpu(0);
 	return 0;
 }
-
-void flush_cache(unsigned long addr, unsigned long size)
-{
-
-}
-
-void icache_enable(void)
-{
-}
-
-void icache_disable(void)
-{
-}
-
-int icache_status(void)
-{
-	return 0;
-}
-
-void dcache_enable(void)
-{
-}
-
-void dcache_disable(void)
-{
-}
-
-int dcache_status(void)
-{
-	return 0;
-}
diff --git a/arch/sh/cpu/sh2/nocache.c b/arch/sh/cpu/sh2/nocache.c
new file mode 100644
index 0000000..06b7f4c
--- /dev/null
+++ b/arch/sh/cpu/sh2/nocache.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 Yoshinori Sato <ysato at users.sourceforge.jp>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/* dummy cache control functions */
+void flush_cache(unsigned long addr, unsigned long size)
+{
+
+}
+
+void icache_enable(void)
+{
+}
+
+void icache_disable(void)
+{
+}
+
+int icache_status(void)
+{
+	return 0;
+}
+
+void dcache_enable(void)
+{
+}
+
+void dcache_disable(void)
+{
+}
+
+int dcache_status(void)
+{
+	return 0;
+}
diff --git a/arch/sh/include/asm/cpu_sh2.h b/arch/sh/include/asm/cpu_sh2.h
index 18a0f0b..b67c093 100644
--- a/arch/sh/include/asm/cpu_sh2.h
+++ b/arch/sh/include/asm/cpu_sh2.h
@@ -8,15 +8,6 @@
 #ifndef _ASM_CPU_SH2_H_
 #define _ASM_CPU_SH2_H_
 
-/* cache control */
-#define CCR_CACHE_STOP		0x00000008
-#define CCR_CACHE_ENABLE	0x00000005
-#define CCR_CACHE_ICI		0x00000008
-
-#define CACHE_OC_ADDRESS_ARRAY	0xf0000000
-#define CACHE_OC_WAY_SHIFT	13
-#define CACHE_OC_NUM_ENTRIES	256
-#define CACHE_OC_ENTRY_SHIFT	4
 
 #if defined(CONFIG_CPU_SH7203)
 # include <asm/cpu_sh7203.h>
-- 
1.8.5.3



More information about the U-Boot mailing list