]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
Implement cache functions for ARM-926ejs
authorLothar Waßmann <LW@KARO-electronics.de>
Tue, 6 Mar 2012 14:12:32 +0000 (15:12 +0100)
committerLothar Waßmann <LW@KARO-electronics.de>
Tue, 6 Mar 2012 14:12:32 +0000 (15:12 +0100)
arch/arm/cpu/arm926ejs/cache.c

index 504f604684d5098b8048338a63ab5dae7d573b55..cc273a7884e37a2d1fb6e8a7ef9b4a6fbc81e0c0 100644 (file)
 #include <linux/types.h>
 #include <common.h>
 
+#define DCACHE_SIZE                    0x4000    // 16KB Size of data cache in bytes
+#define DCACHE_LINE_SIZE               32    // Size of a data cache line
+#define DCACHE_WAYS                    64    // Associativity of the cache
+/*
+ * This is the maximum size of an area which will be invalidated
+ * using the single invalidate entry instructions.  Anything larger
+ * than this, and we go for the whole cache.
+ *
+ * This value should be chosen such that we choose the cheapest
+ * alternative.
+ */
+#define CACHE_DLIMIT                   16384
+
 #ifndef CONFIG_SYS_DCACHE_OFF
-static inline void dcache_noop(void)
+void invalidate_dcache_all(void)
 {
-       if (dcache_status()) {
-               puts("WARNING: cache operations are not implemented!\n"
-                    "WARNING: disabling D-Cache now, you can re-enable it"
-                    "later with 'dcache on' command\n");
-               dcache_disable();
-       }
+       asm volatile (
+               "mcr    p15, 0, %0, c7, c6, 0\n" /* invalidate d-cache */
+               "mcr    p15, 0, %0, c7, c5, 0\n" /* invalidate I cache */
+               "mcr    p15, 0, %0, c7, c10, 4\n" /* data write back */
+               :
+               : "r"(0)
+               : "memory");
 }
 
-void invalidate_dcache_all(void)
+void invalidate_dcache_range(unsigned long start, unsigned long end)
 {
-       dcache_noop();
+       asm volatile (
+#ifndef CONFIG_SYS_ARM_CACHE_WRITETHROUGH
+               "tst    %1, %4\n"
+               "mcrne  p15, 0, %1, c7, c10, 1\n" /* clean D entry */
+               "tst    %2, %4\n"
+               "mcrne  p15, 0, %2, c7, c10, 1\n" /* clean D entry */
+#endif
+               "bic    %1, %1, %4\n"
+               "add    %2, %2, %4\n"
+               "bic    %2, %2, %4\n"
+               "1:\n"
+               "mcr    p15, 0, %1, c7, c6, 1\n" /* invalidate D cache entry */
+               "add    %1, %1, %3\n"
+               "cmp    %1, %2\n"
+               "blo    1b\n"
+               "mcr    p15, 0, %0, c7, c5, 0\n" /* invalidate I cache */
+               "mcr    p15, 0, %0, c7, c10, 4\n" /* data write back */
+               :
+               : "r"(0), "r"(start), "r"(end),
+                 "I"(DCACHE_LINE_SIZE),
+                 "I"(DCACHE_LINE_SIZE - 1)
+               : "memory"
+               );
+
 }
 
-void invalidate_dcache_range(unsigned long start, unsigned long stop)
+#ifndef CONFIG_SYS_ARM_CACHE_WRITETHROUGH
+void flush_dcache_range(unsigned long start, unsigned long end)
 {
-       dcache_noop();
+       if (end - start > CACHE_DLIMIT)
+               flush_dcache_all();
+       else
+               flush_cache(start & ~(SZ_4K - 1), ALIGN(end, SZ_4K));
 }
 
-void flush_dcache_range(unsigned long start, unsigned long stop)
+void flush_cache(unsigned long start, unsigned long end)
 {
-       dcache_noop();
+       asm volatile (
+               "1:\n"
+               "mcr    p15, 0, %1, c7, c14, 1\n" /* clean and invalidate D entry */
+               "add    %1, %1, %3\n"
+               "cmp    %1, %2\n"
+               "blo    1b\n"
+               "mcr    p15, 0, %0, c7, c5, 0\n" /* invalidate I cache */
+               "mcr    p15, 0, %0, c7, c10, 4\n" /* data write back */
+               :
+               : "r"(0), "r"(start), "r"(end), "I"(DCACHE_LINE_SIZE)
+               : "memory"
+               );
 }
+
+void flush_dcache_all(void)
+{
+       asm volatile (
+               "1:\n"
+               "mrc    p15, 0, r15, c7, c14, 3\n" /* test,clean,invalidate */
+               "bne    1b\n"
+               "mcr    p15, 0, %0, c7, c5, 0\n" /* invalidate I cache */
+               "mcr    p15, 0, %0, c7, c10, 4\n" /* data write back */
+               :
+               : "r"(0)
+               : "memory"
+               );
+}
+#else
+void flush_dcache_range(unsigned long start, unsigned long end)
+{
+       invalidate_dcache_range(start, end);
+}
+
+void flush_cache(unsigned long start, unsigned long end)
+{
+       invalidate_dcache_range(start, end);
+}
+
+void flush_dcache_all(void)
+{
+       invalidate_dcache_all();
+}
+#endif /* CONFIG_SYS_ARM_CACHE_WRITETHROUGH */
+
 #else /* #ifndef CONFIG_SYS_DCACHE_OFF */
 void invalidate_dcache_all(void)
 {