[uClinux-dev] [PATCH 8/8] m68knommu: create optimal separate instruction and data cache for ColdFire

Greg Ungerer gerg at snapgear.com
Wed Nov 10 20:48:58 EST 2010


[PATCH 8/8] m68knommu: create optimal separate instruction and data cache for ColdFire

Create separate functions to deal with instruction and data cache flushing.
This way we can optimize them for the vairous cache types and arrangements
used across the ColdFire family.

For example the unified caches in the version 3 cores means we don't
need to flush the instruction cache. For the version 2 cores that do
not do data cacheing (or where we choose instruction cache only) we
don't need to do any data flushing.

Signed-off-by: Greg Ungerer <gerg at uclinux.org>
---
 arch/m68k/include/asm/cacheflush_no.h |   35 +++++++++++++++++++++++++++++---
 arch/m68k/include/asm/m52xxacr.h      |   16 ++++++++++++++-
 arch/m68k/include/asm/m53xxacr.h      |   25 +++++++++++++++++++++++
 arch/m68k/include/asm/m54xxacr.h      |    5 +--
 4 files changed, 73 insertions(+), 8 deletions(-)

diff --git a/arch/m68k/include/asm/cacheflush_no.h b/arch/m68k/include/asm/cacheflush_no.h
index fa361b1..539fe30 100644
--- a/arch/m68k/include/asm/cacheflush_no.h
+++ b/arch/m68k/include/asm/cacheflush_no.h
@@ -12,14 +12,12 @@
 #define flush_cache_dup_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
 #define flush_cache_page(vma, vmaddr)		do { } while (0)
-#ifndef flush_dcache_range
-#define flush_dcache_range(start,len)		__flush_cache_all()
-#endif
+#define flush_dcache_range(start, len)		__flush_dcache_all()
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
 #define flush_dcache_page(page)			do { } while (0)
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
-#define flush_icache_range(start,len)		__flush_cache_all()
+#define flush_icache_range(start, len)		__flush_icache_all()
 #define flush_icache_page(vma,pg)		do { } while (0)
 #define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
 #define flush_cache_vmap(start, end)		do { } while (0)
@@ -46,4 +44,33 @@ static inline void __flush_cache_all(void)
 #endif
 }
 
+/*
+ * Some ColdFire parts implement separate instruction and data caches,
+ * on those we should just flush the appropriate cache. If we don't need
+ * to do any specific flushing then this will be optimized away.
+ */
+static inline void __flush_icache_all(void)
+{
+#ifdef CACHE_INVALIDI
+	__asm__ __volatile__ (
+		"movel	%0, %%d0\n\t"
+		"movec	%%d0, %%CACR\n\t"
+		"nop\n\t"
+		: : "i" (CACHE_INVALIDI) : "d0" );
+#endif
+}
+
+static inline void __flush_dcache_all(void)
+{
+#ifdef CACHE_PUSH
+	mcf_cache_push();
+#endif
+#ifdef CACHE_INVALIDD
+	__asm__ __volatile__ (
+		"movel	%0, %%d0\n\t"
+		"movec	%%d0, %%CACR\n\t"
+		"nop\n\t"
+		: : "i" (CACHE_INVALIDD) : "d0" );
+#endif
+}
 #endif /* _M68KNOMMU_CACHEFLUSH_H */
diff --git a/arch/m68k/include/asm/m52xxacr.h b/arch/m68k/include/asm/m52xxacr.h
index ded5a6e..58fe23d 100644
--- a/arch/m68k/include/asm/m52xxacr.h
+++ b/arch/m68k/include/asm/m52xxacr.h
@@ -60,10 +60,18 @@
  */
 #if defined(CONFIG_CACHE_I)
 #define CACHE_TYPE	CACR_DISD
+#define CACHE_INVTYPEI	0
 #elif defined(CONFIG_CACHE_D)
 #define CACHE_TYPE	CACR_DISI
+#define CACHE_INVTYPED	0
+#elif defined(CONFIG_CACHE_BOTH)
+#define CACHE_TYPE	0
+#define CACHE_INVTYPEI	CACR_INVI
+#define CACHE_INVTYPED	CACR_INVD
 #else
-#define CACHE_TYPE
+/* This is the instruction cache only devices (no split cache) */
+#define CACHE_TYPE	0
+#define CACHE_INVTYPEI	0
 #endif
 
 #if defined(CONFIG_HAVE_CACHE_SPLIT)
@@ -75,6 +83,12 @@
 #endif
 
 #define CACHE_INVALID	(CACHE_MODE + CACR_CINV)
+#if defined(CACHE_INVTYPEI)
+#define CACHE_INVALIDI	(CACHE_MODE + CACR_CINV + CACHE_INVTYPEI)
+#endif
+#if defined(CACHE_INVTYPED)
+#define CACHE_INVALIDD	(CACHE_MODE + CACR_CINV + CACHE_INVTYPED)
+#endif
 
 #define ACR0_MODE	((CONFIG_RAMBASE & 0xff000000) + \
 			 (0x000f0000) + \
diff --git a/arch/m68k/include/asm/m53xxacr.h b/arch/m68k/include/asm/m53xxacr.h
index d8b8dd6..77720f4 100644
--- a/arch/m68k/include/asm/m53xxacr.h
+++ b/arch/m68k/include/asm/m53xxacr.h
@@ -49,12 +49,29 @@
 #define ACR_WPROTECT	0x00000004	/* Write protect region */
 
 /*
+ * Define the cache type and arrangement (needed for pushes).
+ */
+#if defined(CONFIG_M5307)
+#define	CACHE_SIZE	0x2000		/* 8k of unified cache */
+#define	ICACHE_SIZE	CACHE_SIZE
+#define	DCACHE_SIZE	CACHE_SIZE
+#elif defined(CONFIG_M532x)
+#define	CACHE_SIZE	0x4000		/* 32k of unified cache */
+#define	ICACHE_SIZE	CACHE_SIZE
+#define	DCACHE_SIZE	CACHE_SIZE
+#endif
+
+#define	CACHE_LINE_SIZE	16		/* 16 byte line size */
+#define	CACHE_WAYS	4		/* 4 ways - set associative */
+
+/*
  * Set the cache controller settings we will use. This default in the
  * CACR is cache inhibited, we use the ACR register to set cacheing
  * enabled on the regions we want (eg RAM).
  */
 #if defined(CONFIG_CACHE_COPYBACK)
 #define CACHE_TYPE	ACR_CM_CB
+#define CACHE_PUSH
 #else
 #define CACHE_TYPE	ACR_CM_WT
 #endif
@@ -65,7 +82,15 @@
 #define CACHE_MODE	(CACR_EC + CACR_ESB + CACR_DCM_PRE + CACR_EUSP)
 #endif
 
+/*
+ * Unified cache means we will never need to flush for coherency of
+ * instruction fetch. We will need to flush to maintain memory/DMA
+ * coherency though in all cases. And for copyback caches we will need
+ * to push cached data as well.
+ */
 #define CACHE_INIT	CACR_CINVA
+#define CACHE_INVALID	CACR_CINVA
+#define CACHE_INVALIDD	CACR_CINVA
 
 #define ACR0_MODE	((CONFIG_RAMBASE & 0xff000000) + \
 			 (0x000f0000) + \
diff --git a/arch/m68k/include/asm/m54xxacr.h b/arch/m68k/include/asm/m54xxacr.h
index 96b9777..eff6f28 100644
--- a/arch/m68k/include/asm/m54xxacr.h
+++ b/arch/m68k/include/asm/m54xxacr.h
@@ -82,14 +82,13 @@
 
 #define CACHE_INIT	(CACR_DCINVA+CACR_BCINVA+CACR_ICINVA)
 #define CACHE_INVALID	(CACHE_MODE+CACR_DCINVA+CACR_BCINVA+CACR_ICINVA)
+#define CACHE_INVALIDI	(CACHE_MODE+CACR_BCINVA+CACR_ICINVA)
+#define CACHE_INVALIDD	(CACHE_MODE+CACR_DCINVA)
 #define ACR0_MODE	(0x000f0000+DATA_CACHE_MODE)
 #define ACR1_MODE	0
 #define ACR2_MODE	(0x000f0000+INSN_CACHE_MODE)
 #define ACR3_MODE	0
 
-#if ((DATA_CACHE_MODE & ACR_CM) == ACR_CM_WT)
-#define flush_dcache_range(a, l) do { asm("nop"); } while (0)
-#endif
 #if ((DATA_CACHE_MODE & ACR_CM) == ACR_CM_CP)
 /* Copyback cache mode must push dirty cache lines first */
 #define	CACHE_PUSH
-- 
1.7.0.4




More information about the uClinux-dev mailing list