Merge tag 'u-boot-atmel-fixes-2020.07-a' of https://gitlab.denx.de/u-boot/custodians...
[oweals/u-boot.git] / arch / nds32 / lib / cache.c
index 0f1a886d3048b1f68687336bbe39a20ed655fdfb..21917e5da5e6618deadc4a9599148bb8ca575843 100644 (file)
@@ -1,51 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (C) 2012 Andes Technology Corporation
  * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com>
  * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307         USA
- *
  */
 
 #include <common.h>
+#include <cpu_func.h>
+#if !(CONFIG_IS_ENABLED(SYS_ICACHE_OFF) && CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
+#include <asm/cache.h>
+static inline unsigned long CACHE_SET(unsigned char cache)
+{
+       if (cache == ICACHE)
+               return 64 << ((GET_ICM_CFG() & ICM_CFG_MSK_ISET) \
+                       >> ICM_CFG_OFF_ISET);
+       else
+               return 64 << ((GET_DCM_CFG() & DCM_CFG_MSK_DSET) \
+                       >> DCM_CFG_OFF_DSET);
+}
+
+static inline unsigned long CACHE_WAY(unsigned char cache)
+{
+       if (cache == ICACHE)
+               return 1 + ((GET_ICM_CFG() & ICM_CFG_MSK_IWAY) \
+                       >> ICM_CFG_OFF_IWAY);
+       else
+               return 1 + ((GET_DCM_CFG() & DCM_CFG_MSK_DWAY) \
+                       >> DCM_CFG_OFF_DWAY);
+}
 
 static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache)
 {
        if (cache == ICACHE)
                return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \
-                                       >> ICM_CFG_OFF_ISZ) - 1);
+                       >> ICM_CFG_OFF_ISZ) - 1);
        else
                return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \
-                                       >> DCM_CFG_OFF_DSZ) - 1);
+                       >> DCM_CFG_OFF_DSZ) - 1);
 }
+#endif
 
-void flush_dcache_range(unsigned long start, unsigned long end)
+#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
+void invalidate_icache_all(void)
 {
-       unsigned long line_size;
+       unsigned long end, line_size;
+       line_size = CACHE_LINE_SIZE(ICACHE);
+       end = line_size * CACHE_WAY(ICACHE) * CACHE_SET(ICACHE);
+       do {
+               end -= line_size;
+               __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
 
-       line_size = CACHE_LINE_SIZE(DCACHE);
+               end -= line_size;
+               __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
 
-       while (end > start) {
-               asm volatile (
-                       "\n\tcctl %0, L1D_VA_WB"
-                       "\n\tcctl %0, L1D_VA_INVAL"
-                       :
-                       : "r" (start)
-               );
-               start += line_size;
-       }
+               end -= line_size;
+               __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
+               end -= line_size;
+               __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
+       } while (end > 0);
 }
 
 void invalidate_icache_range(unsigned long start, unsigned long end)
@@ -63,27 +75,6 @@ void invalidate_icache_range(unsigned long start, unsigned long end)
        }
 }
 
-void invalidate_dcache_range(unsigned long start, unsigned long end)
-{
-       unsigned long line_size;
-
-       line_size = CACHE_LINE_SIZE(DCACHE);
-       while (end > start) {
-               asm volatile (
-                       "\n\tcctl %0, L1D_VA_INVAL"
-                       :
-                       : "r"(start)
-               );
-               start += line_size;
-       }
-}
-
-void flush_cache(unsigned long addr, unsigned long size)
-{
-       flush_dcache_range(addr, addr + size);
-       invalidate_icache_range(addr, addr + size);
-}
-
 void icache_enable(void)
 {
        asm volatile (
@@ -120,6 +111,81 @@ int icache_status(void)
        return ret;
 }
 
+#else
+void invalidate_icache_all(void)
+{
+}
+
+void invalidate_icache_range(unsigned long start, unsigned long end)
+{
+}
+
+void icache_enable(void)
+{
+}
+
+void icache_disable(void)
+{
+}
+
+int icache_status(void)
+{
+       return 0;
+}
+
+#endif
+
+#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
+void dcache_wbinval_all(void)
+{
+       unsigned long end, line_size;
+       line_size = CACHE_LINE_SIZE(DCACHE);
+       end = line_size * CACHE_WAY(DCACHE) * CACHE_SET(DCACHE);
+       do {
+               end -= line_size;
+               __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
+               __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
+               end -= line_size;
+               __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
+               __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
+               end -= line_size;
+               __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
+               __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
+               end -= line_size;
+               __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
+               __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
+
+       } while (end > 0);
+}
+
+void flush_dcache_range(unsigned long start, unsigned long end)
+{
+       unsigned long line_size;
+
+       line_size = CACHE_LINE_SIZE(DCACHE);
+
+       while (end > start) {
+               asm volatile (
+                       "\n\tcctl %0, L1D_VA_WB"
+                       "\n\tcctl %0, L1D_VA_INVAL" : : "r" (start)
+               );
+               start += line_size;
+       }
+}
+
+void invalidate_dcache_range(unsigned long start, unsigned long end)
+{
+       unsigned long line_size;
+
+       line_size = CACHE_LINE_SIZE(DCACHE);
+       while (end > start) {
+               asm volatile (
+                       "\n\tcctl %0, L1D_VA_INVAL" : : "r"(start)
+               );
+               start += line_size;
+       }
+}
+
 void dcache_enable(void)
 {
        asm volatile (
@@ -144,7 +210,6 @@ void dcache_disable(void)
 int dcache_status(void)
 {
        int ret;
-
        asm volatile (
                "mfsr   $p0, $mr8\n\t"
                "andi   %0, $p0, 0x02\n\t"
@@ -152,6 +217,52 @@ int dcache_status(void)
                :
                : "memory"
        );
-
        return ret;
 }
+
+#else
+void dcache_wbinval_all(void)
+{
+}
+
+void flush_dcache_range(unsigned long start, unsigned long end)
+{
+}
+
+void invalidate_dcache_range(unsigned long start, unsigned long end)
+{
+}
+
+void dcache_enable(void)
+{
+}
+
+void dcache_disable(void)
+{
+}
+
+int dcache_status(void)
+{
+       return 0;
+}
+
+#endif
+
+
+void flush_dcache_all(void)
+{
+       dcache_wbinval_all();
+}
+
+void cache_flush(void)
+{
+       flush_dcache_all();
+       invalidate_icache_all();
+}
+
+
+void flush_cache(unsigned long addr, unsigned long size)
+{
+       flush_dcache_range(addr, addr + size);
+       invalidate_icache_range(addr, addr + size);
+}