]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - arch/arc/lib/cache.c
arc: add support for SLC (System Level Cache, AKA L2-cache)
[people/ms/u-boot.git] / arch / arc / lib / cache.c
index a2277231ba127ad2d03eb8a5ffcc5439d6223aa7..e369e5a8569702913d126da2bb2feaa25f1c1c72 100644 (file)
@@ -16,6 +16,7 @@
 #define DC_CTRL_INV_MODE_FLUSH (1 << 6)
 #define DC_CTRL_FLUSH_STATUS   (1 << 8)
 #define CACHE_VER_NUM_MASK     0xF
+#define SLC_CTRL_SB            (1 << 2)
 
 int icache_status(void)
 {
@@ -49,10 +50,12 @@ void icache_disable(void)
 
 void invalidate_icache_all(void)
 {
-#ifndef CONFIG_SYS_ICACHE_OFF
+       /* If no cache in CPU exit immediately */
+       if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
+               return;
+
        /* Any write to IC_IVIC register triggers invalidation of entire I$ */
        write_aux_reg(ARC_AUX_IC_IVIC, 1);
-#endif /* CONFIG_SYS_ICACHE_OFF */
 }
 
 int dcache_status(void)
@@ -156,13 +159,60 @@ void invalidate_dcache_range(unsigned long start, unsigned long end)
 
 void invalidate_dcache_all(void)
 {
-#ifndef CONFIG_SYS_DCACHE_OFF
+       /* If no cache in CPU exit immediately */
+       if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
+               return;
+
        /* Write 1 to DC_IVDC register triggers invalidation of entire D$ */
        write_aux_reg(ARC_AUX_DC_IVDC, 1);
-#endif /* CONFIG_SYS_DCACHE_OFF */
 }
 
 void flush_cache(unsigned long start, unsigned long size)
 {
        flush_dcache_range(start, start + size);
 }
+
+#ifdef CONFIG_ISA_ARCV2
+void slc_enable(void)
+{
+       /* If SLC ver = 0, no SLC present in CPU */
+       if (!(read_aux_reg(ARC_BCR_SLC) & 0xff))
+               return;
+
+       write_aux_reg(ARC_AUX_SLC_CONTROL,
+                     read_aux_reg(ARC_AUX_SLC_CONTROL) & ~1);
+}
+
+void slc_disable(void)
+{
+       /* If SLC ver = 0, no SLC present in CPU */
+       if (!(read_aux_reg(ARC_BCR_SLC) & 0xff))
+               return;
+
+       write_aux_reg(ARC_AUX_SLC_CONTROL,
+                     read_aux_reg(ARC_AUX_SLC_CONTROL) | 1);
+}
+
+void slc_flush(void)
+{
+       /* If SLC ver = 0, no SLC present in CPU */
+       if (!(read_aux_reg(ARC_BCR_SLC) & 0xff))
+               return;
+
+       write_aux_reg(ARC_AUX_SLC_FLUSH, 1);
+
+       /* Wait flush end */
+       while (read_aux_reg(ARC_AUX_SLC_CONTROL) & SLC_CTRL_SB)
+               ;
+}
+
+void slc_invalidate(void)
+{
+       /* If SLC ver = 0, no SLC present in CPU */
+       if (!(read_aux_reg(ARC_BCR_SLC) & 0xff))
+               return;
+
+       write_aux_reg(ARC_AUX_SLC_INVALIDATE, 1);
+}
+
+#endif /* CONFIG_ISA_ARCV2 */