diff options
author | Alexey Brodkin <abrodkin@synopsys.com> | 2015-03-30 13:36:04 +0300 |
---|---|---|
committer | Alexey Brodkin <abrodkin@synopsys.com> | 2015-04-03 09:47:50 +0300 |
commit | 6eb15e50f48927c65a67371555b5afc24b3c7d21 (patch) | |
tree | 0e6f7a560fece41ed04cfdd3fad6591433c56e19 | |
parent | 09424d11192cffd4793b7bc922c5b47d4fe88a4d (diff) | |
download | u-boot-imx-6eb15e50f48927c65a67371555b5afc24b3c7d21.zip u-boot-imx-6eb15e50f48927c65a67371555b5afc24b3c7d21.tar.gz u-boot-imx-6eb15e50f48927c65a67371555b5afc24b3c7d21.tar.bz2 |
arc: add support for SLC (System Level Cache, AKA L2-cache)
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>
-rw-r--r-- | arch/arc/include/asm/arcregs.h | 4 | ||||
-rw-r--r-- | arch/arc/include/asm/cache.h | 11 | ||||
-rw-r--r-- | arch/arc/lib/cache.c | 46 | ||||
-rw-r--r-- | arch/arc/lib/start.S | 4 |
4 files changed, 65 insertions, 0 deletions
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index 6a36a81..0e11dcc 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -46,6 +46,10 @@ #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 */ diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index 8a77cd9..0b3ebd9 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -27,4 +27,15 @@ #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 */ diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 30f045a..e369e5a 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -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 */ diff --git a/arch/arc/lib/start.S b/arch/arc/lib/start.S index 48ee86e..e1ef19c 100644 --- a/arch/arc/lib/start.S +++ b/arch/arc/lib/start.S @@ -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 |