Merge tag 'u-boot-rockchip-20200501' of https://gitlab.denx.de/u-boot/custodians...
[platform/kernel/u-boot.git] / arch / mips / lib / cache.c
index bd14ba6..1a8c87d 100644 (file)
@@ -1,14 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * (C) Copyright 2003
  * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
+#include <cpu_func.h>
 #include <asm/cacheops.h>
+#ifdef CONFIG_MIPS_L2_CACHE
 #include <asm/cm.h>
+#endif
+#include <asm/io.h>
 #include <asm/mipsregs.h>
+#include <asm/system.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -84,7 +88,7 @@ static inline unsigned long scache_line_size(void)
 #ifdef CONFIG_MIPS_L2_CACHE
        return gd->arch.l2_line_size;
 #else
-       return 0;
+       return CONFIG_SYS_SCACHE_LINE_SIZE;
 #endif
 }
 
@@ -94,6 +98,9 @@ static inline unsigned long scache_line_size(void)
        const unsigned int cache_ops[] = { ops };                       \
        unsigned int i;                                                 \
                                                                        \
+       if (!lsize)                                                     \
+               break;                                                  \
+                                                                       \
        for (; addr <= aend; addr += lsize) {                           \
                for (i = 0; i < ARRAY_SIZE(cache_ops); i++)             \
                        mips_cache(cache_ops[i], addr);                 \
@@ -114,22 +121,27 @@ void flush_cache(ulong start_addr, ulong size)
                /* flush I-cache & D-cache simultaneously */
                cache_loop(start_addr, start_addr + size, ilsize,
                           HIT_WRITEBACK_INV_D, HIT_INVALIDATE_I);
-               return;
+               goto ops_done;
        }
 
        /* flush D-cache */
        cache_loop(start_addr, start_addr + size, dlsize, HIT_WRITEBACK_INV_D);
 
        /* flush L2 cache */
-       if (slsize)
-               cache_loop(start_addr, start_addr + size, slsize,
-                          HIT_WRITEBACK_INV_SD);
+       cache_loop(start_addr, start_addr + size, slsize, HIT_WRITEBACK_INV_SD);
 
        /* flush I-cache */
        cache_loop(start_addr, start_addr + size, ilsize, HIT_INVALIDATE_I);
+
+ops_done:
+       /* ensure cache ops complete before any further memory accesses */
+       sync();
+
+       /* ensure the pipeline doesn't contain now-invalid instructions */
+       instruction_hazard_barrier();
 }
 
-void flush_dcache_range(ulong start_addr, ulong stop)
+void __weak flush_dcache_range(ulong start_addr, ulong stop)
 {
        unsigned long lsize = dcache_line_size();
        unsigned long slsize = scache_line_size();
@@ -141,8 +153,10 @@ void flush_dcache_range(ulong start_addr, ulong stop)
        cache_loop(start_addr, stop, lsize, HIT_WRITEBACK_INV_D);
 
        /* flush L2 cache */
-       if (slsize)
-               cache_loop(start_addr, stop, slsize, HIT_WRITEBACK_INV_SD);
+       cache_loop(start_addr, stop, slsize, HIT_WRITEBACK_INV_SD);
+
+       /* ensure cache ops complete before any further memory accesses */
+       sync();
 }
 
 void invalidate_dcache_range(ulong start_addr, ulong stop)
@@ -155,8 +169,30 @@ void invalidate_dcache_range(ulong start_addr, ulong stop)
                return;
 
        /* invalidate L2 cache */
-       if (slsize)
-               cache_loop(start_addr, stop, slsize, HIT_INVALIDATE_SD);
+       cache_loop(start_addr, stop, slsize, HIT_INVALIDATE_SD);
 
        cache_loop(start_addr, stop, lsize, HIT_INVALIDATE_D);
+
+       /* ensure cache ops complete before any further memory accesses */
+       sync();
+}
+
+int dcache_status(void)
+{
+       unsigned int cca = read_c0_config() & CONF_CM_CMASK;
+       return cca != CONF_CM_UNCACHED;
+}
+
+void dcache_enable(void)
+{
+       puts("Not supported!\n");
+}
+
+void dcache_disable(void)
+{
+       /* change CCA to uncached */
+       change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+
+       /* ensure the pipeline doesn't contain now-invalid instructions */
+       instruction_hazard_barrier();
 }