nios2: convert cache flush to use dm cpu data
authorThomas Chou <thomas@wytron.com.tw>
Thu, 22 Oct 2015 23:58:20 +0000 (07:58 +0800)
committerThomas Chou <thomas@wytron.com.tw>
Thu, 22 Oct 2015 23:58:20 +0000 (07:58 +0800)
Convert cache flush to use dm cpu data.

The original cache flush functions are written in assembly
and use CONFIG_SYS_{I,D}CACHE_SIZE... macros. It is difficult
to convert to use cache configuration in dm cpu data which is
extracted from device tree.

The cacheflush.c of Linux nios2 arch uses cpuinfo structure,
which is very close to our dm cpu data. So we copy and modify
it to arch/nios2/lib/cache.c to replace the old cache.S.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
arch/nios2/cpu/cpu.c
arch/nios2/include/asm/cache.h
arch/nios2/lib/bootm.c
arch/nios2/lib/cache.S [deleted file]
arch/nios2/lib/cache.c [new file with mode: 0644]

index 0e71b4384214d9304d4f715d203525e2c1a1fb87..e4217c8a2c77de25c33d5a102e903b78dffa3ccf 100644 (file)
@@ -29,21 +29,6 @@ int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        return 0;
 }
 
-int dcache_status(void)
-{
-       return 1;
-}
-
-void dcache_enable(void)
-{
-       flush_dcache(CONFIG_SYS_DCACHE_SIZE, CONFIG_SYS_DCACHELINE_SIZE);
-}
-
-void dcache_disable(void)
-{
-       flush_dcache(CONFIG_SYS_DCACHE_SIZE, CONFIG_SYS_DCACHELINE_SIZE);
-}
-
 int arch_cpu_init_dm(void)
 {
        struct udevice *dev;
index 9b87c9f755f1731a52fc024d91ef81a1e0fd128c..dde43cd6fc788fc856882ed6fdda666236d2a6c1 100644 (file)
@@ -8,18 +8,11 @@
 #ifndef __ASM_NIOS2_CACHE_H_
 #define __ASM_NIOS2_CACHE_H_
 
-extern void flush_dcache (unsigned long start, unsigned long size);
-extern void flush_icache (unsigned long start, unsigned long size);
-
 /*
- * Valid L1 data cache line sizes for the NIOS2 architecture are 4, 16, and 32
- * bytes.  If the board configuration has not specified one we default to the
- * largest of these values for alignment of DMA buffers.
+ * Valid L1 data cache line sizes for the NIOS2 architecture are 4,
+ * 16, and 32 bytes. We default to the largest of these values for
+ * alignment of DMA buffers.
  */
-#ifdef CONFIG_SYS_CACHELINE_SIZE
-#define ARCH_DMA_MINALIGN      CONFIG_SYS_CACHELINE_SIZE
-#else
 #define ARCH_DMA_MINALIGN      32
-#endif
 
 #endif /* __ASM_NIOS2_CACHE_H_ */
index c730a3fd08b242d480183534338fce7f1f849d1a..4e5c269193d9d32ee7dc83650a6d7a88e47aedb6 100644 (file)
@@ -6,9 +6,6 @@
  */
 
 #include <common.h>
-#include <command.h>
-#include <asm/byteorder.h>
-#include <asm/cache.h>
 
 #define NIOS_MAGIC 0x534f494e /* enable command line and initrd passing */
 
@@ -40,8 +37,7 @@ int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *ima
 
        /* flushes data and instruction caches before calling the kernel */
        disable_interrupts();
-       flush_dcache((ulong)kernel, CONFIG_SYS_DCACHE_SIZE);
-       flush_icache((ulong)kernel, CONFIG_SYS_ICACHE_SIZE);
+       flush_dcache_all();
 
        debug("bootargs=%s @ 0x%lx\n", commandline, (ulong)&commandline);
        debug("initrd=0x%lx-0x%lx\n", (ulong)initrd_start, (ulong)initrd_end);
diff --git a/arch/nios2/lib/cache.S b/arch/nios2/lib/cache.S
deleted file mode 100644 (file)
index 683f005..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
- * Scott McNutt <smcnutt@psyent.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <config.h>
-
-       .text
-
-       .global flush_dcache
-
-flush_dcache:
-       add     r5, r5, r4
-       movhi   r8, %hi(CONFIG_SYS_DCACHELINE_SIZE)
-       ori     r8, r8, %lo(CONFIG_SYS_DCACHELINE_SIZE)
-0:     flushd  0(r4)
-       add     r4, r4, r8
-       bltu    r4, r5, 0b
-       ret
-
-
-       .global flush_icache
-
-flush_icache:
-       add     r5, r5, r4
-       movhi   r8, %hi(CONFIG_SYS_ICACHELINE_SIZE)
-       ori     r8, r8, %lo(CONFIG_SYS_ICACHELINE_SIZE)
-1:     flushi  r4
-       add     r4, r4, r8
-       bltu    r4, r5, 1b
-       ret
-
-       .global flush_dcache_range
-
-flush_dcache_range:
-       movhi   r8, %hi(CONFIG_SYS_DCACHELINE_SIZE)
-       ori     r8, r8, %lo(CONFIG_SYS_DCACHELINE_SIZE)
-0:     flushd  0(r4)
-       add     r4, r4, r8
-       bltu    r4, r5, 0b
-       ret
-
-       .global flush_cache
-
-flush_cache:
-       add     r5, r5, r4
-       mov     r9, r4
-       mov     r10, r5
-
-       movhi   r8, %hi(CONFIG_SYS_DCACHELINE_SIZE)
-       ori     r8, r8, %lo(CONFIG_SYS_DCACHELINE_SIZE)
-0:     flushd  0(r4)
-       add     r4, r4, r8
-       bltu    r4, r5, 0b
-
-       mov     r4, r9
-       mov     r5, r10
-       movhi   r8, %hi(CONFIG_SYS_ICACHELINE_SIZE)
-       ori     r8, r8, %lo(CONFIG_SYS_ICACHELINE_SIZE)
-1:     flushi  r4
-       add     r4, r4, r8
-       bltu    r4, r5, 1b
-
-       sync
-       flushp
-       ret
diff --git a/arch/nios2/lib/cache.c b/arch/nios2/lib/cache.c
new file mode 100644 (file)
index 0000000..7c74e1a
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ * Copyright (C) 2009, Wind River Systems Inc
+ * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/cache.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void __flush_dcache(unsigned long start, unsigned long end)
+{
+       unsigned long addr;
+
+       start &= ~(gd->arch.dcache_line_size - 1);
+       end += (gd->arch.dcache_line_size - 1);
+       end &= ~(gd->arch.dcache_line_size - 1);
+
+       for (addr = start; addr < end; addr += gd->arch.dcache_line_size) {
+               __asm__ __volatile__ ("   flushda 0(%0)\n"
+                                       : /* Outputs */
+                                       : /* Inputs  */ "r"(addr)
+                                       /* : No clobber */);
+       }
+}
+
+static void __flush_dcache_all(unsigned long start, unsigned long end)
+{
+       unsigned long addr;
+
+       start &= ~(gd->arch.dcache_line_size - 1);
+       end += (gd->arch.dcache_line_size - 1);
+       end &= ~(gd->arch.dcache_line_size - 1);
+
+       if (end > start + gd->arch.dcache_size)
+               end = start + gd->arch.dcache_size;
+
+       for (addr = start; addr < end; addr += gd->arch.dcache_line_size) {
+               __asm__ __volatile__ ("   flushd 0(%0)\n"
+                                       : /* Outputs */
+                                       : /* Inputs  */ "r"(addr)
+                                       /* : No clobber */);
+       }
+}
+
+static void __invalidate_dcache(unsigned long start, unsigned long end)
+{
+       unsigned long addr;
+
+       start &= ~(gd->arch.dcache_line_size - 1);
+       end += (gd->arch.dcache_line_size - 1);
+       end &= ~(gd->arch.dcache_line_size - 1);
+
+       for (addr = start; addr < end; addr += gd->arch.dcache_line_size) {
+               __asm__ __volatile__ ("   initda 0(%0)\n"
+                                       : /* Outputs */
+                                       : /* Inputs  */ "r"(addr)
+                                       /* : No clobber */);
+       }
+}
+
+static void __flush_icache(unsigned long start, unsigned long end)
+{
+       unsigned long addr;
+
+       start &= ~(gd->arch.icache_line_size - 1);
+       end += (gd->arch.icache_line_size - 1);
+       end &= ~(gd->arch.icache_line_size - 1);
+
+       if (end > start + gd->arch.icache_size)
+               end = start + gd->arch.icache_size;
+
+       for (addr = start; addr < end; addr += gd->arch.icache_line_size) {
+               __asm__ __volatile__ ("   flushi %0\n"
+                                       : /* Outputs */
+                                       : /* Inputs  */ "r"(addr)
+                                       /* : No clobber */);
+       }
+       __asm__ __volatile(" flushp\n");
+}
+
+void flush_dcache_all(void)
+{
+       __flush_dcache_all(0, gd->arch.dcache_size);
+       __flush_icache(0, gd->arch.icache_size);
+}
+
+void flush_dcache_range(unsigned long start, unsigned long end)
+{
+       if (gd->arch.has_initda)
+               __flush_dcache(start, end);
+       else
+               __flush_dcache_all(start, end);
+}
+
+void flush_cache(unsigned long start, unsigned long size)
+{
+       if (gd->arch.has_initda)
+               __flush_dcache(start, start + size);
+       else
+               __flush_dcache_all(start, start + size);
+       __flush_icache(start, start + size);
+}
+
+void invalidate_dcache_range(unsigned long start, unsigned long end)
+{
+       if (gd->arch.has_initda)
+               __invalidate_dcache(start, end);
+       else
+               __flush_dcache_all(start, end);
+}
+
+int dcache_status(void)
+{
+       return 1;
+}
+
+void dcache_enable(void)
+{
+       flush_dcache_all();
+}
+
+void dcache_disable(void)
+{
+       flush_dcache_all();
+}