arc: add support for SLC (System Level Cache, AKA L2-cache)
authorAlexey Brodkin <abrodkin@synopsys.com>
Mon, 30 Mar 2015 10:36:04 +0000 (13:36 +0300)
committerAlexey Brodkin <abrodkin@synopsys.com>
Fri, 3 Apr 2015 06:47:50 +0000 (09:47 +0300)
ARCv2 cores may have built-in SLC (System Level Cache, AKA L2-cache).
This change adds functions required for controlling SLC:
 * slc_enable/disable
 * slc_flush/invalidate

For now we just disable SLC to escape DMA coherency issues until either:
 * SLC flush/invalidate is supported in DMA APIin U-Boot
 * hardware DMA coherency is implemented (that might be board specific
   so probably we'll need to have a separate Kconfig option for
   controlling SLC explicitly)

Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
arch/arc/include/asm/arcregs.h
arch/arc/include/asm/cache.h
arch/arc/lib/cache.c
arch/arc/lib/start.S

index 6a36a81c0f1545680089b9ad3c8d03ace0bff613..0e11dcced5c87db6e8b8d6c06ac21ed8c0ff9e1f 100644 (file)
 #define ARC_AUX_DC_PTAG                0x5C
 #endif
 #define ARC_BCR_DC_BUILD       0x72
+#define ARC_BCR_SLC            0xce
+#define ARC_AUX_SLC_CONTROL    0x903
+#define ARC_AUX_SLC_FLUSH      0x904
+#define ARC_AUX_SLC_INVALIDATE 0x905
 
 #ifndef __ASSEMBLY__
 /* Accessors for auxiliary registers */
index 8a77cd93af2c1d317e7813e83a2e154233ead8eb..0b3ebd9f58555a54ad284f28fcaa6ca6bb2b797f 100644 (file)
 #define CONFIG_ARC_MMU_VER 4
 #endif
 
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_ISA_ARCV2
+void slc_enable(void);
+void slc_disable(void);
+void slc_flush(void);
+void slc_invalidate(void);
+#endif
+
+#endif /* __ASSEMBLY__ */
+
 #endif /* __ASM_ARC_CACHE_H */
index 30f045a864b68c44524005db417b326812205bd8..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)
 {
@@ -170,3 +171,48 @@ 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 */
index 48ee86e54adf506ebcf26c0eb91cea1c0675635f..e1ef19cb88997d8a998c463a6997d3733499895d 100644 (file)
@@ -18,6 +18,10 @@ ENTRY(_start)
        mov     %fp, %sp
 
        /* Unconditionally disable caches */
+#ifdef CONFIG_ISA_ARCV2
+       bl      slc_flush
+       bl      slc_disable
+#endif
        bl      flush_dcache_all
        bl      dcache_disable
        bl      icache_disable