|
@@ -5,13 +5,12 @@
|
|
|
*/
|
|
|
|
|
|
#include <config.h>
|
|
|
+#include <common.h>
|
|
|
#include <linux/compiler.h>
|
|
|
#include <linux/kernel.h>
|
|
|
#include <asm/arcregs.h>
|
|
|
#include <asm/cache.h>
|
|
|
|
|
|
-#define CACHE_LINE_MASK (~(CONFIG_SYS_CACHELINE_SIZE - 1))
|
|
|
-
|
|
|
/* Bit values in IC_CTRL */
|
|
|
#define IC_CTRL_CACHE_DISABLE (1 << 0)
|
|
|
|
|
@@ -26,12 +25,18 @@
|
|
|
#define OP_FLUSH 0x2
|
|
|
#define OP_INV_IC 0x3
|
|
|
|
|
|
-#ifdef CONFIG_ISA_ARCV2
|
|
|
/*
|
|
|
* By default that variable will fall into .bss section.
|
|
|
* But .bss section is not relocated and so it will be initilized before
|
|
|
* relocation but will be used after being zeroed.
|
|
|
*/
|
|
|
+int l1_line_sz __section(".data");
|
|
|
+int dcache_exists __section(".data");
|
|
|
+int icache_exists __section(".data");
|
|
|
+
|
|
|
+#define CACHE_LINE_MASK (~(l1_line_sz - 1))
|
|
|
+
|
|
|
+#ifdef CONFIG_ISA_ARCV2
|
|
|
int slc_line_sz __section(".data");
|
|
|
int slc_exists __section(".data");
|
|
|
|
|
@@ -111,46 +116,87 @@ static inline void __slc_line_op(unsigned long paddr, unsigned long sz,
|
|
|
#define __slc_line_op(paddr, sz, cacheop)
|
|
|
#endif
|
|
|
|
|
|
-static inline int icache_exists(void)
|
|
|
+#ifdef CONFIG_ISA_ARCV2
|
|
|
+static void read_decode_cache_bcr_arcv2(void)
|
|
|
{
|
|
|
- /* Check if Instruction Cache is available */
|
|
|
- if (read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)
|
|
|
- return 1;
|
|
|
- else
|
|
|
- return 0;
|
|
|
+ union {
|
|
|
+ struct {
|
|
|
+#ifdef CONFIG_CPU_BIG_ENDIAN
|
|
|
+ unsigned int pad:24, way:2, lsz:2, sz:4;
|
|
|
+#else
|
|
|
+ unsigned int sz:4, lsz:2, way:2, pad:24;
|
|
|
+#endif
|
|
|
+ } fields;
|
|
|
+ unsigned int word;
|
|
|
+ } slc_cfg;
|
|
|
+
|
|
|
+ union {
|
|
|
+ struct {
|
|
|
+#ifdef CONFIG_CPU_BIG_ENDIAN
|
|
|
+ unsigned int pad:24, ver:8;
|
|
|
+#else
|
|
|
+ unsigned int ver:8, pad:24;
|
|
|
+#endif
|
|
|
+ } fields;
|
|
|
+ unsigned int word;
|
|
|
+ } sbcr;
|
|
|
+
|
|
|
+ sbcr.word = read_aux_reg(ARC_BCR_SLC);
|
|
|
+ if (sbcr.fields.ver) {
|
|
|
+ slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG);
|
|
|
+ slc_exists = 1;
|
|
|
+ slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64;
|
|
|
+ }
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
-static inline int dcache_exists(void)
|
|
|
+void read_decode_cache_bcr(void)
|
|
|
{
|
|
|
- /* Check if Data Cache is available */
|
|
|
- if (read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)
|
|
|
- return 1;
|
|
|
- else
|
|
|
- return 0;
|
|
|
+ int dc_line_sz = 0, ic_line_sz = 0;
|
|
|
+
|
|
|
+ union {
|
|
|
+ struct {
|
|
|
+#ifdef CONFIG_CPU_BIG_ENDIAN
|
|
|
+ unsigned int pad:12, line_len:4, sz:4, config:4, ver:8;
|
|
|
+#else
|
|
|
+ unsigned int ver:8, config:4, sz:4, line_len:4, pad:12;
|
|
|
+#endif
|
|
|
+ } fields;
|
|
|
+ unsigned int word;
|
|
|
+ } ibcr, dbcr;
|
|
|
+
|
|
|
+ ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD);
|
|
|
+ if (ibcr.fields.ver) {
|
|
|
+ icache_exists = 1;
|
|
|
+ l1_line_sz = ic_line_sz = 8 << ibcr.fields.line_len;
|
|
|
+ if (!ic_line_sz)
|
|
|
+ panic("Instruction exists but line length is 0\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD);
|
|
|
+ if (dbcr.fields.ver){
|
|
|
+ dcache_exists = 1;
|
|
|
+ l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len;
|
|
|
+ if (!dc_line_sz)
|
|
|
+ panic("Data cache exists but line length is 0\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ic_line_sz && dc_line_sz && (ic_line_sz != dc_line_sz))
|
|
|
+ panic("Instruction and data cache line lengths differ\n");
|
|
|
}
|
|
|
|
|
|
void cache_init(void)
|
|
|
{
|
|
|
+ read_decode_cache_bcr();
|
|
|
+
|
|
|
#ifdef CONFIG_ISA_ARCV2
|
|
|
- /* Check if System-Level Cache (SLC) is available */
|
|
|
- if (read_aux_reg(ARC_BCR_SLC) & CACHE_VER_NUM_MASK) {
|
|
|
-#define LSIZE_OFFSET 4
|
|
|
-#define LSIZE_MASK 3
|
|
|
- if (read_aux_reg(ARC_AUX_SLC_CONFIG) &
|
|
|
- (LSIZE_MASK << LSIZE_OFFSET))
|
|
|
- slc_line_sz = 64;
|
|
|
- else
|
|
|
- slc_line_sz = 128;
|
|
|
- slc_exists = 1;
|
|
|
- } else {
|
|
|
- slc_exists = 0;
|
|
|
- }
|
|
|
+ read_decode_cache_bcr_arcv2();
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
int icache_status(void)
|
|
|
{
|
|
|
- if (!icache_exists())
|
|
|
+ if (!icache_exists)
|
|
|
return 0;
|
|
|
|
|
|
if (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE)
|
|
@@ -161,14 +207,14 @@ int icache_status(void)
|
|
|
|
|
|
void icache_enable(void)
|
|
|
{
|
|
|
- if (icache_exists())
|
|
|
+ if (icache_exists)
|
|
|
write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) &
|
|
|
~IC_CTRL_CACHE_DISABLE);
|
|
|
}
|
|
|
|
|
|
void icache_disable(void)
|
|
|
{
|
|
|
- if (icache_exists())
|
|
|
+ if (icache_exists)
|
|
|
write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) |
|
|
|
IC_CTRL_CACHE_DISABLE);
|
|
|
}
|
|
@@ -190,7 +236,7 @@ void invalidate_icache_all(void)
|
|
|
|
|
|
int dcache_status(void)
|
|
|
{
|
|
|
- if (!dcache_exists())
|
|
|
+ if (!dcache_exists)
|
|
|
return 0;
|
|
|
|
|
|
if (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE)
|
|
@@ -201,7 +247,7 @@ int dcache_status(void)
|
|
|
|
|
|
void dcache_enable(void)
|
|
|
{
|
|
|
- if (!dcache_exists())
|
|
|
+ if (!dcache_exists)
|
|
|
return;
|
|
|
|
|
|
write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) &
|
|
@@ -210,7 +256,7 @@ void dcache_enable(void)
|
|
|
|
|
|
void dcache_disable(void)
|
|
|
{
|
|
|
- if (!dcache_exists())
|
|
|
+ if (!dcache_exists)
|
|
|
return;
|
|
|
|
|
|
write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) |
|
|
@@ -246,14 +292,14 @@ static inline void __cache_line_loop(unsigned long paddr, unsigned long sz,
|
|
|
sz += paddr & ~CACHE_LINE_MASK;
|
|
|
paddr &= CACHE_LINE_MASK;
|
|
|
|
|
|
- num_lines = DIV_ROUND_UP(sz, CONFIG_SYS_CACHELINE_SIZE);
|
|
|
+ num_lines = DIV_ROUND_UP(sz, l1_line_sz);
|
|
|
|
|
|
while (num_lines-- > 0) {
|
|
|
#if (CONFIG_ARC_MMU_VER == 3)
|
|
|
write_aux_reg(aux_tag, paddr);
|
|
|
#endif
|
|
|
write_aux_reg(aux_cmd, paddr);
|
|
|
- paddr += CONFIG_SYS_CACHELINE_SIZE;
|
|
|
+ paddr += l1_line_sz;
|
|
|
}
|
|
|
}
|
|
|
|