|
|
|
@ -24,6 +24,7 @@
|
|
|
|
|
char *arc_cache_mumbojumbo(int c, char *buf, int len)
|
|
|
|
|
{
|
|
|
|
|
int n = 0;
|
|
|
|
|
struct cpuinfo_arc_cache *p;
|
|
|
|
|
|
|
|
|
|
#define PR_CACHE(p, cfg, str) \
|
|
|
|
|
if (!(p)->ver) \
|
|
|
|
@ -39,6 +40,11 @@ char *arc_cache_mumbojumbo(int c, char *buf, int len)
|
|
|
|
|
PR_CACHE(&cpuinfo_arc700[c].icache, CONFIG_ARC_HAS_ICACHE, "I-Cache");
|
|
|
|
|
PR_CACHE(&cpuinfo_arc700[c].dcache, CONFIG_ARC_HAS_DCACHE, "D-Cache");
|
|
|
|
|
|
|
|
|
|
p = &cpuinfo_arc700[c].slc;
|
|
|
|
|
if (p->ver)
|
|
|
|
|
n += scnprintf(buf + n, len - n,
|
|
|
|
|
"SLC\t\t: %uK, %uB Line\n", p->sz_k, p->line_len);
|
|
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -49,7 +55,7 @@ char *arc_cache_mumbojumbo(int c, char *buf, int len)
|
|
|
|
|
*/
|
|
|
|
|
void read_decode_cache_bcr(void)
|
|
|
|
|
{
|
|
|
|
|
struct cpuinfo_arc_cache *p_ic, *p_dc;
|
|
|
|
|
struct cpuinfo_arc_cache *p_ic, *p_dc, *p_slc;
|
|
|
|
|
unsigned int cpu = smp_processor_id();
|
|
|
|
|
struct bcr_cache {
|
|
|
|
|
#ifdef CONFIG_CPU_BIG_ENDIAN
|
|
|
|
@ -59,14 +65,29 @@ void read_decode_cache_bcr(void)
|
|
|
|
|
#endif
|
|
|
|
|
} ibcr, dbcr;
|
|
|
|
|
|
|
|
|
|
struct bcr_generic sbcr;
|
|
|
|
|
|
|
|
|
|
struct bcr_slc_cfg {
|
|
|
|
|
#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
|
|
|
|
|
} slc_cfg;
|
|
|
|
|
|
|
|
|
|
p_ic = &cpuinfo_arc700[cpu].icache;
|
|
|
|
|
READ_BCR(ARC_REG_IC_BCR, ibcr);
|
|
|
|
|
|
|
|
|
|
if (!ibcr.ver)
|
|
|
|
|
goto dc_chk;
|
|
|
|
|
|
|
|
|
|
BUG_ON(ibcr.config != 3);
|
|
|
|
|
p_ic->assoc = 2; /* Fixed to 2w set assoc */
|
|
|
|
|
if (ibcr.ver <= 3) {
|
|
|
|
|
BUG_ON(ibcr.config != 3);
|
|
|
|
|
p_ic->assoc = 2; /* Fixed to 2w set assoc */
|
|
|
|
|
} else if (ibcr.ver >= 4) {
|
|
|
|
|
p_ic->assoc = 1 << ibcr.config; /* 1,2,4,8 */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_ic->line_len = 8 << ibcr.line_len;
|
|
|
|
|
p_ic->sz_k = 1 << (ibcr.sz - 1);
|
|
|
|
|
p_ic->ver = ibcr.ver;
|
|
|
|
@ -78,15 +99,32 @@ dc_chk:
|
|
|
|
|
READ_BCR(ARC_REG_DC_BCR, dbcr);
|
|
|
|
|
|
|
|
|
|
if (!dbcr.ver)
|
|
|
|
|
return;
|
|
|
|
|
goto slc_chk;
|
|
|
|
|
|
|
|
|
|
if (dbcr.ver <= 3) {
|
|
|
|
|
BUG_ON(dbcr.config != 2);
|
|
|
|
|
p_dc->assoc = 4; /* Fixed to 4w set assoc */
|
|
|
|
|
p_dc->vipt = 1;
|
|
|
|
|
p_dc->alias = p_dc->sz_k/p_dc->assoc/TO_KB(PAGE_SIZE) > 1;
|
|
|
|
|
} else if (dbcr.ver >= 4) {
|
|
|
|
|
p_dc->assoc = 1 << dbcr.config; /* 1,2,4,8 */
|
|
|
|
|
p_dc->vipt = 0;
|
|
|
|
|
p_dc->alias = 0; /* PIPT so can't VIPT alias */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BUG_ON(dbcr.config != 2);
|
|
|
|
|
p_dc->assoc = 4; /* Fixed to 4w set assoc */
|
|
|
|
|
p_dc->line_len = 16 << dbcr.line_len;
|
|
|
|
|
p_dc->sz_k = 1 << (dbcr.sz - 1);
|
|
|
|
|
p_dc->ver = dbcr.ver;
|
|
|
|
|
p_dc->vipt = 1;
|
|
|
|
|
p_dc->alias = p_dc->sz_k/p_dc->assoc/TO_KB(PAGE_SIZE) > 1;
|
|
|
|
|
|
|
|
|
|
slc_chk:
|
|
|
|
|
p_slc = &cpuinfo_arc700[cpu].slc;
|
|
|
|
|
READ_BCR(ARC_REG_SLC_BCR, sbcr);
|
|
|
|
|
if (sbcr.ver) {
|
|
|
|
|
READ_BCR(ARC_REG_SLC_CFG, slc_cfg);
|
|
|
|
|
p_slc->ver = sbcr.ver;
|
|
|
|
|
p_slc->sz_k = 128 << slc_cfg.sz;
|
|
|
|
|
p_slc->line_len = (slc_cfg.lsz == 0) ? 128 : 64;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -225,10 +263,53 @@ void __cache_line_loop_v3(unsigned long paddr, unsigned long vaddr,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* In HS38x (MMU v4), although icache is VIPT, only paddr is needed for cache
|
|
|
|
|
* maintenance ops (in IVIL reg), as long as icache doesn't alias.
|
|
|
|
|
*
|
|
|
|
|
* For Aliasing icache, vaddr is also needed (in IVIL), while paddr is
|
|
|
|
|
* specified in PTAG (similar to MMU v3)
|
|
|
|
|
*/
|
|
|
|
|
static inline
|
|
|
|
|
void __cache_line_loop_v4(unsigned long paddr, unsigned long vaddr,
|
|
|
|
|
unsigned long sz, const int cacheop)
|
|
|
|
|
{
|
|
|
|
|
unsigned int aux_cmd;
|
|
|
|
|
int num_lines;
|
|
|
|
|
const int full_page_op = __builtin_constant_p(sz) && sz == PAGE_SIZE;
|
|
|
|
|
|
|
|
|
|
if (cacheop == OP_INV_IC) {
|
|
|
|
|
aux_cmd = ARC_REG_IC_IVIL;
|
|
|
|
|
} else {
|
|
|
|
|
/* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */
|
|
|
|
|
aux_cmd = cacheop & OP_INV ? ARC_REG_DC_IVDL : ARC_REG_DC_FLDL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Ensure we properly floor/ceil the non-line aligned/sized requests
|
|
|
|
|
* and have @paddr - aligned to cache line and integral @num_lines.
|
|
|
|
|
* This however can be avoided for page sized since:
|
|
|
|
|
* -@paddr will be cache-line aligned already (being page aligned)
|
|
|
|
|
* -@sz will be integral multiple of line size (being page sized).
|
|
|
|
|
*/
|
|
|
|
|
if (!full_page_op) {
|
|
|
|
|
sz += paddr & ~CACHE_LINE_MASK;
|
|
|
|
|
paddr &= CACHE_LINE_MASK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
num_lines = DIV_ROUND_UP(sz, L1_CACHE_BYTES);
|
|
|
|
|
|
|
|
|
|
while (num_lines-- > 0) {
|
|
|
|
|
write_aux_reg(aux_cmd, paddr);
|
|
|
|
|
paddr += L1_CACHE_BYTES;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if (CONFIG_ARC_MMU_VER < 3)
|
|
|
|
|
#define __cache_line_loop __cache_line_loop_v2
|
|
|
|
|
#elif (CONFIG_ARC_MMU_VER == 3)
|
|
|
|
|
#define __cache_line_loop __cache_line_loop_v3
|
|
|
|
|
#elif (CONFIG_ARC_MMU_VER > 3)
|
|
|
|
|
#define __cache_line_loop __cache_line_loop_v4
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_ARC_HAS_DCACHE
|
|
|
|
@ -669,7 +750,6 @@ void arc_cache_init(void)
|
|
|
|
|
|
|
|
|
|
if (IS_ENABLED(CONFIG_ARC_HAS_DCACHE)) {
|
|
|
|
|
struct cpuinfo_arc_cache *dc = &cpuinfo_arc700[cpu].dcache;
|
|
|
|
|
int handled;
|
|
|
|
|
|
|
|
|
|
if (!dc->ver)
|
|
|
|
|
panic("cache support enabled but non-existent cache\n");
|
|
|
|
@ -678,12 +758,14 @@ void arc_cache_init(void)
|
|
|
|
|
panic("DCache line [%d] != kernel Config [%d]",
|
|
|
|
|
dc->line_len, L1_CACHE_BYTES);
|
|
|
|
|
|
|
|
|
|
/* check for D-Cache aliasing */
|
|
|
|
|
handled = IS_ENABLED(CONFIG_ARC_CACHE_VIPT_ALIASING);
|
|
|
|
|
/* check for D-Cache aliasing on ARCompact: ARCv2 has PIPT */
|
|
|
|
|
if (is_isa_arcompact()) {
|
|
|
|
|
int handled = IS_ENABLED(CONFIG_ARC_CACHE_VIPT_ALIASING);
|
|
|
|
|
|
|
|
|
|
if (dc->alias && !handled)
|
|
|
|
|
panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
|
|
|
|
|
else if (!dc->alias && handled)
|
|
|
|
|
panic("Disable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
|
|
|
|
|
if (dc->alias && !handled)
|
|
|
|
|
panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
|
|
|
|
|
else if (!dc->alias && handled)
|
|
|
|
|
panic("Disable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|