summaryrefslogtreecommitdiffstats
path: root/arch/arm/cpu/cache.c
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2012-09-28 00:14:14 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2012-10-13 11:19:13 +0200
commit1dbfd5ed82fd2b6b0ba6df98e2e23aaf3cd1a197 (patch)
tree3214217a66047c49aaa48ea3e860dec9ac7899bb /arch/arm/cpu/cache.c
parent3d76ff9aeada3607e913e4627237c6fd7b5acc05 (diff)
downloadbarebox-1dbfd5ed82fd2b6b0ba6df98e2e23aaf3cd1a197.tar.gz
barebox-1dbfd5ed82fd2b6b0ba6df98e2e23aaf3cd1a197.tar.xz
ARM: Support multiple ARM architectures
The different ARM architectures need different cache functions. This patch makes them selectable during runtime. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/arm/cpu/cache.c')
-rw-r--r--arch/arm/cpu/cache.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/arch/arm/cpu/cache.c b/arch/arm/cpu/cache.c
new file mode 100644
index 0000000000..1254609bb6
--- /dev/null
+++ b/arch/arm/cpu/cache.c
@@ -0,0 +1,103 @@
+#include <common.h>
+#include <init.h>
+#include <asm/mmu.h>
+#include <asm/cache.h>
+#include <asm/system_info.h>
+
+int arm_architecture;
+
+struct cache_fns {
+ void (*dma_clean_range)(unsigned long start, unsigned long end);
+ void (*dma_flush_range)(unsigned long start, unsigned long end);
+ void (*dma_inv_range)(unsigned long start, unsigned long end);
+ void (*mmu_cache_on)(void);
+ void (*mmu_cache_off)(void);
+ void (*mmu_cache_flush)(void);
+};
+
+struct cache_fns *cache_fns;
+
+#define DEFINE_CPU_FNS(arch) \
+ void arch##_dma_clean_range(unsigned long start, unsigned long end); \
+ void arch##_dma_flush_range(unsigned long start, unsigned long end); \
+ void arch##_dma_inv_range(unsigned long start, unsigned long end); \
+ void arch##_mmu_cache_on(void); \
+ void arch##_mmu_cache_off(void); \
+ void arch##_mmu_cache_flush(void); \
+ \
+ static struct cache_fns __maybe_unused cache_fns_arm##arch = { \
+ .dma_clean_range = arch##_dma_clean_range, \
+ .dma_flush_range = arch##_dma_flush_range, \
+ .dma_inv_range = arch##_dma_inv_range, \
+ .mmu_cache_on = arch##_mmu_cache_on, \
+ .mmu_cache_off = arch##_mmu_cache_off, \
+ .mmu_cache_flush = arch##_mmu_cache_flush, \
+ };
+
+DEFINE_CPU_FNS(v4)
+DEFINE_CPU_FNS(v5)
+DEFINE_CPU_FNS(v6)
+DEFINE_CPU_FNS(v7)
+
+void __dma_clean_range(unsigned long start, unsigned long end)
+{
+ cache_fns->dma_clean_range(start, end);
+}
+
+void __dma_flush_range(unsigned long start, unsigned long end)
+{
+ cache_fns->dma_flush_range(start, end);
+}
+
+void __dma_inv_range(unsigned long start, unsigned long end)
+{
+ cache_fns->dma_inv_range(start, end);
+}
+
+void __mmu_cache_on(void)
+{
+ cache_fns->mmu_cache_on();
+}
+
+void __mmu_cache_off(void)
+{
+ cache_fns->mmu_cache_off();
+}
+
+void __mmu_cache_flush(void)
+{
+ cache_fns->mmu_cache_flush();
+}
+
+int arm_set_cache_functions(void)
+{
+ switch (cpu_architecture()) {
+#ifdef CONFIG_CPU_32v4T
+ case CPU_ARCH_ARMv4T:
+ cache_fns = &cache_fns_armv4;
+ break;
+#endif
+#ifdef CONFIG_CPU_32v5
+ case CPU_ARCH_ARMv5:
+ case CPU_ARCH_ARMv5T:
+ case CPU_ARCH_ARMv5TE:
+ case CPU_ARCH_ARMv5TEJ:
+ cache_fns = &cache_fns_armv5;
+ break;
+#endif
+#ifdef CONFIG_CPU_32v6
+ case CPU_ARCH_ARMv6:
+ cache_fns = &cache_fns_armv6;
+ break;
+#endif
+#ifdef CONFIG_CPU_32v7
+ case CPU_ARCH_ARMv7:
+ cache_fns = &cache_fns_armv7;
+ break;
+#endif
+ default:
+ BUG();
+ }
+
+ return 0;
+}