1660d5f0dSAlexey Brodkin /* 2660d5f0dSAlexey Brodkin * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. 3660d5f0dSAlexey Brodkin * 4660d5f0dSAlexey Brodkin * SPDX-License-Identifier: GPL-2.0+ 5660d5f0dSAlexey Brodkin */ 6660d5f0dSAlexey Brodkin 7660d5f0dSAlexey Brodkin #include <config.h> 8*379b3280SAlexey Brodkin #include <common.h> 9ef639e6fSAlexey Brodkin #include <linux/compiler.h> 10ef639e6fSAlexey Brodkin #include <linux/kernel.h> 11660d5f0dSAlexey Brodkin #include <asm/arcregs.h> 12205e7a7bSAlexey Brodkin #include <asm/cache.h> 13660d5f0dSAlexey Brodkin 14660d5f0dSAlexey Brodkin /* Bit values in IC_CTRL */ 15660d5f0dSAlexey Brodkin #define IC_CTRL_CACHE_DISABLE (1 << 0) 16660d5f0dSAlexey Brodkin 17660d5f0dSAlexey Brodkin /* Bit values in DC_CTRL */ 18660d5f0dSAlexey Brodkin #define DC_CTRL_CACHE_DISABLE (1 << 0) 19660d5f0dSAlexey Brodkin #define DC_CTRL_INV_MODE_FLUSH (1 << 6) 20660d5f0dSAlexey Brodkin #define DC_CTRL_FLUSH_STATUS (1 << 8) 21660d5f0dSAlexey Brodkin #define CACHE_VER_NUM_MASK 0xF 226eb15e50SAlexey Brodkin #define SLC_CTRL_SB (1 << 2) 23660d5f0dSAlexey Brodkin 24ef639e6fSAlexey Brodkin #define OP_INV 0x1 25ef639e6fSAlexey Brodkin #define OP_FLUSH 0x2 26ef639e6fSAlexey Brodkin #define OP_INV_IC 0x3 27ef639e6fSAlexey Brodkin 28ef639e6fSAlexey Brodkin /* 29ef639e6fSAlexey Brodkin * By default that variable will fall into .bss section. 30ef639e6fSAlexey Brodkin * But .bss section is not relocated and so it will be initilized before 31ef639e6fSAlexey Brodkin * relocation but will be used after being zeroed. 32ef639e6fSAlexey Brodkin */ 33*379b3280SAlexey Brodkin int l1_line_sz __section(".data"); 34*379b3280SAlexey Brodkin int dcache_exists __section(".data"); 35*379b3280SAlexey Brodkin int icache_exists __section(".data"); 36*379b3280SAlexey Brodkin 37*379b3280SAlexey Brodkin #define CACHE_LINE_MASK (~(l1_line_sz - 1)) 38*379b3280SAlexey Brodkin 39*379b3280SAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 40ef639e6fSAlexey Brodkin int slc_line_sz __section(".data"); 41ef639e6fSAlexey Brodkin int slc_exists __section(".data"); 42ef639e6fSAlexey Brodkin 43ef639e6fSAlexey Brodkin static unsigned int __before_slc_op(const int op) 44ef639e6fSAlexey Brodkin { 45ef639e6fSAlexey Brodkin unsigned int reg = reg; 46ef639e6fSAlexey Brodkin 47ef639e6fSAlexey Brodkin if (op == OP_INV) { 48ef639e6fSAlexey Brodkin /* 49ef639e6fSAlexey Brodkin * IM is set by default and implies Flush-n-inv 50ef639e6fSAlexey Brodkin * Clear it here for vanilla inv 51ef639e6fSAlexey Brodkin */ 52ef639e6fSAlexey Brodkin reg = read_aux_reg(ARC_AUX_SLC_CTRL); 53ef639e6fSAlexey Brodkin write_aux_reg(ARC_AUX_SLC_CTRL, reg & ~DC_CTRL_INV_MODE_FLUSH); 54ef639e6fSAlexey Brodkin } 55ef639e6fSAlexey Brodkin 56ef639e6fSAlexey Brodkin return reg; 57ef639e6fSAlexey Brodkin } 58ef639e6fSAlexey Brodkin 59ef639e6fSAlexey Brodkin static void __after_slc_op(const int op, unsigned int reg) 60ef639e6fSAlexey Brodkin { 61ef639e6fSAlexey Brodkin if (op & OP_FLUSH) /* flush / flush-n-inv both wait */ 62ef639e6fSAlexey Brodkin while (read_aux_reg(ARC_AUX_SLC_CTRL) & 63ef639e6fSAlexey Brodkin DC_CTRL_FLUSH_STATUS) 64ef639e6fSAlexey Brodkin ; 65ef639e6fSAlexey Brodkin 66ef639e6fSAlexey Brodkin /* Switch back to default Invalidate mode */ 67ef639e6fSAlexey Brodkin if (op == OP_INV) 68ef639e6fSAlexey Brodkin write_aux_reg(ARC_AUX_SLC_CTRL, reg | DC_CTRL_INV_MODE_FLUSH); 69ef639e6fSAlexey Brodkin } 70ef639e6fSAlexey Brodkin 71ef639e6fSAlexey Brodkin static inline void __slc_line_loop(unsigned long paddr, unsigned long sz, 72ef639e6fSAlexey Brodkin const int op) 73ef639e6fSAlexey Brodkin { 74ef639e6fSAlexey Brodkin unsigned int aux_cmd; 75ef639e6fSAlexey Brodkin int num_lines; 76ef639e6fSAlexey Brodkin 77ef639e6fSAlexey Brodkin #define SLC_LINE_MASK (~(slc_line_sz - 1)) 78ef639e6fSAlexey Brodkin 79ef639e6fSAlexey Brodkin aux_cmd = op & OP_INV ? ARC_AUX_SLC_IVDL : ARC_AUX_SLC_FLDL; 80ef639e6fSAlexey Brodkin 81ef639e6fSAlexey Brodkin sz += paddr & ~SLC_LINE_MASK; 82ef639e6fSAlexey Brodkin paddr &= SLC_LINE_MASK; 83ef639e6fSAlexey Brodkin 84ef639e6fSAlexey Brodkin num_lines = DIV_ROUND_UP(sz, slc_line_sz); 85ef639e6fSAlexey Brodkin 86ef639e6fSAlexey Brodkin while (num_lines-- > 0) { 87ef639e6fSAlexey Brodkin write_aux_reg(aux_cmd, paddr); 88ef639e6fSAlexey Brodkin paddr += slc_line_sz; 89ef639e6fSAlexey Brodkin } 90ef639e6fSAlexey Brodkin } 91ef639e6fSAlexey Brodkin 92ef639e6fSAlexey Brodkin static inline void __slc_entire_op(const int cacheop) 93ef639e6fSAlexey Brodkin { 94ef639e6fSAlexey Brodkin int aux; 95ef639e6fSAlexey Brodkin unsigned int ctrl_reg = __before_slc_op(cacheop); 96ef639e6fSAlexey Brodkin 97ef639e6fSAlexey Brodkin if (cacheop & OP_INV) /* Inv or flush-n-inv use same cmd reg */ 98ef639e6fSAlexey Brodkin aux = ARC_AUX_SLC_INVALIDATE; 99ef639e6fSAlexey Brodkin else 100ef639e6fSAlexey Brodkin aux = ARC_AUX_SLC_FLUSH; 101ef639e6fSAlexey Brodkin 102ef639e6fSAlexey Brodkin write_aux_reg(aux, 0x1); 103ef639e6fSAlexey Brodkin 104ef639e6fSAlexey Brodkin __after_slc_op(cacheop, ctrl_reg); 105ef639e6fSAlexey Brodkin } 106ef639e6fSAlexey Brodkin 107ef639e6fSAlexey Brodkin static inline void __slc_line_op(unsigned long paddr, unsigned long sz, 108ef639e6fSAlexey Brodkin const int cacheop) 109ef639e6fSAlexey Brodkin { 110ef639e6fSAlexey Brodkin unsigned int ctrl_reg = __before_slc_op(cacheop); 111ef639e6fSAlexey Brodkin __slc_line_loop(paddr, sz, cacheop); 112ef639e6fSAlexey Brodkin __after_slc_op(cacheop, ctrl_reg); 113ef639e6fSAlexey Brodkin } 114ef639e6fSAlexey Brodkin #else 115ef639e6fSAlexey Brodkin #define __slc_entire_op(cacheop) 116ef639e6fSAlexey Brodkin #define __slc_line_op(paddr, sz, cacheop) 117ef639e6fSAlexey Brodkin #endif 118ef639e6fSAlexey Brodkin 119*379b3280SAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 120*379b3280SAlexey Brodkin static void read_decode_cache_bcr_arcv2(void) 121ef639e6fSAlexey Brodkin { 122*379b3280SAlexey Brodkin union { 123*379b3280SAlexey Brodkin struct { 124*379b3280SAlexey Brodkin #ifdef CONFIG_CPU_BIG_ENDIAN 125*379b3280SAlexey Brodkin unsigned int pad:24, way:2, lsz:2, sz:4; 126*379b3280SAlexey Brodkin #else 127*379b3280SAlexey Brodkin unsigned int sz:4, lsz:2, way:2, pad:24; 128*379b3280SAlexey Brodkin #endif 129*379b3280SAlexey Brodkin } fields; 130*379b3280SAlexey Brodkin unsigned int word; 131*379b3280SAlexey Brodkin } slc_cfg; 132*379b3280SAlexey Brodkin 133*379b3280SAlexey Brodkin union { 134*379b3280SAlexey Brodkin struct { 135*379b3280SAlexey Brodkin #ifdef CONFIG_CPU_BIG_ENDIAN 136*379b3280SAlexey Brodkin unsigned int pad:24, ver:8; 137*379b3280SAlexey Brodkin #else 138*379b3280SAlexey Brodkin unsigned int ver:8, pad:24; 139*379b3280SAlexey Brodkin #endif 140*379b3280SAlexey Brodkin } fields; 141*379b3280SAlexey Brodkin unsigned int word; 142*379b3280SAlexey Brodkin } sbcr; 143*379b3280SAlexey Brodkin 144*379b3280SAlexey Brodkin sbcr.word = read_aux_reg(ARC_BCR_SLC); 145*379b3280SAlexey Brodkin if (sbcr.fields.ver) { 146*379b3280SAlexey Brodkin slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG); 147*379b3280SAlexey Brodkin slc_exists = 1; 148*379b3280SAlexey Brodkin slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64; 149*379b3280SAlexey Brodkin } 150*379b3280SAlexey Brodkin } 151*379b3280SAlexey Brodkin #endif 152*379b3280SAlexey Brodkin 153*379b3280SAlexey Brodkin void read_decode_cache_bcr(void) 154*379b3280SAlexey Brodkin { 155*379b3280SAlexey Brodkin int dc_line_sz = 0, ic_line_sz = 0; 156*379b3280SAlexey Brodkin 157*379b3280SAlexey Brodkin union { 158*379b3280SAlexey Brodkin struct { 159*379b3280SAlexey Brodkin #ifdef CONFIG_CPU_BIG_ENDIAN 160*379b3280SAlexey Brodkin unsigned int pad:12, line_len:4, sz:4, config:4, ver:8; 161*379b3280SAlexey Brodkin #else 162*379b3280SAlexey Brodkin unsigned int ver:8, config:4, sz:4, line_len:4, pad:12; 163*379b3280SAlexey Brodkin #endif 164*379b3280SAlexey Brodkin } fields; 165*379b3280SAlexey Brodkin unsigned int word; 166*379b3280SAlexey Brodkin } ibcr, dbcr; 167*379b3280SAlexey Brodkin 168*379b3280SAlexey Brodkin ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD); 169*379b3280SAlexey Brodkin if (ibcr.fields.ver) { 170*379b3280SAlexey Brodkin icache_exists = 1; 171*379b3280SAlexey Brodkin l1_line_sz = ic_line_sz = 8 << ibcr.fields.line_len; 172*379b3280SAlexey Brodkin if (!ic_line_sz) 173*379b3280SAlexey Brodkin panic("Instruction exists but line length is 0\n"); 174ef639e6fSAlexey Brodkin } 175ef639e6fSAlexey Brodkin 176*379b3280SAlexey Brodkin dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD); 177*379b3280SAlexey Brodkin if (dbcr.fields.ver){ 178*379b3280SAlexey Brodkin dcache_exists = 1; 179*379b3280SAlexey Brodkin l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len; 180*379b3280SAlexey Brodkin if (!dc_line_sz) 181*379b3280SAlexey Brodkin panic("Data cache exists but line length is 0\n"); 182*379b3280SAlexey Brodkin } 183*379b3280SAlexey Brodkin 184*379b3280SAlexey Brodkin if (ic_line_sz && dc_line_sz && (ic_line_sz != dc_line_sz)) 185*379b3280SAlexey Brodkin panic("Instruction and data cache line lengths differ\n"); 186ef639e6fSAlexey Brodkin } 187ef639e6fSAlexey Brodkin 188ef639e6fSAlexey Brodkin void cache_init(void) 189ef639e6fSAlexey Brodkin { 190*379b3280SAlexey Brodkin read_decode_cache_bcr(); 191*379b3280SAlexey Brodkin 192ef639e6fSAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 193*379b3280SAlexey Brodkin read_decode_cache_bcr_arcv2(); 194ef639e6fSAlexey Brodkin #endif 195ef639e6fSAlexey Brodkin } 196ef639e6fSAlexey Brodkin 197660d5f0dSAlexey Brodkin int icache_status(void) 198660d5f0dSAlexey Brodkin { 199*379b3280SAlexey Brodkin if (!icache_exists) 200660d5f0dSAlexey Brodkin return 0; 201660d5f0dSAlexey Brodkin 202ef639e6fSAlexey Brodkin if (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE) 203ef639e6fSAlexey Brodkin return 0; 204ef639e6fSAlexey Brodkin else 205ef639e6fSAlexey Brodkin return 1; 206660d5f0dSAlexey Brodkin } 207660d5f0dSAlexey Brodkin 208660d5f0dSAlexey Brodkin void icache_enable(void) 209660d5f0dSAlexey Brodkin { 210*379b3280SAlexey Brodkin if (icache_exists) 211660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) & 212660d5f0dSAlexey Brodkin ~IC_CTRL_CACHE_DISABLE); 213660d5f0dSAlexey Brodkin } 214660d5f0dSAlexey Brodkin 215660d5f0dSAlexey Brodkin void icache_disable(void) 216660d5f0dSAlexey Brodkin { 217*379b3280SAlexey Brodkin if (icache_exists) 218660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) | 219660d5f0dSAlexey Brodkin IC_CTRL_CACHE_DISABLE); 220660d5f0dSAlexey Brodkin } 221660d5f0dSAlexey Brodkin 222ef639e6fSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF 223660d5f0dSAlexey Brodkin void invalidate_icache_all(void) 224660d5f0dSAlexey Brodkin { 225660d5f0dSAlexey Brodkin /* Any write to IC_IVIC register triggers invalidation of entire I$ */ 226ef639e6fSAlexey Brodkin if (icache_status()) { 227660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_IVIC, 1); 228ef639e6fSAlexey Brodkin read_aux_reg(ARC_AUX_IC_CTRL); /* blocks */ 229660d5f0dSAlexey Brodkin } 230ef639e6fSAlexey Brodkin } 231ef639e6fSAlexey Brodkin #else 232ef639e6fSAlexey Brodkin void invalidate_icache_all(void) 233ef639e6fSAlexey Brodkin { 234ef639e6fSAlexey Brodkin } 235ef639e6fSAlexey Brodkin #endif 236660d5f0dSAlexey Brodkin 237660d5f0dSAlexey Brodkin int dcache_status(void) 238660d5f0dSAlexey Brodkin { 239*379b3280SAlexey Brodkin if (!dcache_exists) 240660d5f0dSAlexey Brodkin return 0; 241660d5f0dSAlexey Brodkin 242ef639e6fSAlexey Brodkin if (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) 243ef639e6fSAlexey Brodkin return 0; 244ef639e6fSAlexey Brodkin else 245ef639e6fSAlexey Brodkin return 1; 246660d5f0dSAlexey Brodkin } 247660d5f0dSAlexey Brodkin 248660d5f0dSAlexey Brodkin void dcache_enable(void) 249660d5f0dSAlexey Brodkin { 250*379b3280SAlexey Brodkin if (!dcache_exists) 251660d5f0dSAlexey Brodkin return; 252660d5f0dSAlexey Brodkin 253660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) & 254660d5f0dSAlexey Brodkin ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE)); 255660d5f0dSAlexey Brodkin } 256660d5f0dSAlexey Brodkin 257660d5f0dSAlexey Brodkin void dcache_disable(void) 258660d5f0dSAlexey Brodkin { 259*379b3280SAlexey Brodkin if (!dcache_exists) 260660d5f0dSAlexey Brodkin return; 261660d5f0dSAlexey Brodkin 262660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) | 263660d5f0dSAlexey Brodkin DC_CTRL_CACHE_DISABLE); 264660d5f0dSAlexey Brodkin } 265660d5f0dSAlexey Brodkin 266660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF 267660d5f0dSAlexey Brodkin /* 268ef639e6fSAlexey Brodkin * Common Helper for Line Operations on {I,D}-Cache 269660d5f0dSAlexey Brodkin */ 270ef639e6fSAlexey Brodkin static inline void __cache_line_loop(unsigned long paddr, unsigned long sz, 271ef639e6fSAlexey Brodkin const int cacheop) 272660d5f0dSAlexey Brodkin { 273ef639e6fSAlexey Brodkin unsigned int aux_cmd; 274ef639e6fSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 275ef639e6fSAlexey Brodkin unsigned int aux_tag; 276ef639e6fSAlexey Brodkin #endif 277ef639e6fSAlexey Brodkin int num_lines; 278660d5f0dSAlexey Brodkin 279ef639e6fSAlexey Brodkin if (cacheop == OP_INV_IC) { 280ef639e6fSAlexey Brodkin aux_cmd = ARC_AUX_IC_IVIL; 281ef639e6fSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 282ef639e6fSAlexey Brodkin aux_tag = ARC_AUX_IC_PTAG; 283ef639e6fSAlexey Brodkin #endif 284ef639e6fSAlexey Brodkin } else { 285ef639e6fSAlexey Brodkin /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */ 286ef639e6fSAlexey Brodkin aux_cmd = cacheop & OP_INV ? ARC_AUX_DC_IVDL : ARC_AUX_DC_FLDL; 287ef639e6fSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 288ef639e6fSAlexey Brodkin aux_tag = ARC_AUX_DC_PTAG; 289ef639e6fSAlexey Brodkin #endif 290660d5f0dSAlexey Brodkin } 291660d5f0dSAlexey Brodkin 292ef639e6fSAlexey Brodkin sz += paddr & ~CACHE_LINE_MASK; 293ef639e6fSAlexey Brodkin paddr &= CACHE_LINE_MASK; 294ef639e6fSAlexey Brodkin 295*379b3280SAlexey Brodkin num_lines = DIV_ROUND_UP(sz, l1_line_sz); 296ef639e6fSAlexey Brodkin 297ef639e6fSAlexey Brodkin while (num_lines-- > 0) { 298ef639e6fSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 299ef639e6fSAlexey Brodkin write_aux_reg(aux_tag, paddr); 300ef639e6fSAlexey Brodkin #endif 301ef639e6fSAlexey Brodkin write_aux_reg(aux_cmd, paddr); 302*379b3280SAlexey Brodkin paddr += l1_line_sz; 303ef639e6fSAlexey Brodkin } 304ef639e6fSAlexey Brodkin } 305ef639e6fSAlexey Brodkin 306ef639e6fSAlexey Brodkin static unsigned int __before_dc_op(const int op) 307ef639e6fSAlexey Brodkin { 308ef639e6fSAlexey Brodkin unsigned int reg; 309ef639e6fSAlexey Brodkin 310ef639e6fSAlexey Brodkin if (op == OP_INV) { 311ef639e6fSAlexey Brodkin /* 312ef639e6fSAlexey Brodkin * IM is set by default and implies Flush-n-inv 313ef639e6fSAlexey Brodkin * Clear it here for vanilla inv 314ef639e6fSAlexey Brodkin */ 315ef639e6fSAlexey Brodkin reg = read_aux_reg(ARC_AUX_DC_CTRL); 316ef639e6fSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, reg & ~DC_CTRL_INV_MODE_FLUSH); 317ef639e6fSAlexey Brodkin } 318ef639e6fSAlexey Brodkin 319ef639e6fSAlexey Brodkin return reg; 320ef639e6fSAlexey Brodkin } 321ef639e6fSAlexey Brodkin 322ef639e6fSAlexey Brodkin static void __after_dc_op(const int op, unsigned int reg) 323ef639e6fSAlexey Brodkin { 324ef639e6fSAlexey Brodkin if (op & OP_FLUSH) /* flush / flush-n-inv both wait */ 325ef639e6fSAlexey Brodkin while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) 326ef639e6fSAlexey Brodkin ; 327ef639e6fSAlexey Brodkin 328ef639e6fSAlexey Brodkin /* Switch back to default Invalidate mode */ 329ef639e6fSAlexey Brodkin if (op == OP_INV) 330ef639e6fSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, reg | DC_CTRL_INV_MODE_FLUSH); 331ef639e6fSAlexey Brodkin } 332ef639e6fSAlexey Brodkin 333ef639e6fSAlexey Brodkin static inline void __dc_entire_op(const int cacheop) 334ef639e6fSAlexey Brodkin { 335ef639e6fSAlexey Brodkin int aux; 336ef639e6fSAlexey Brodkin unsigned int ctrl_reg = __before_dc_op(cacheop); 337ef639e6fSAlexey Brodkin 338ef639e6fSAlexey Brodkin if (cacheop & OP_INV) /* Inv or flush-n-inv use same cmd reg */ 339ef639e6fSAlexey Brodkin aux = ARC_AUX_DC_IVDC; 340ef639e6fSAlexey Brodkin else 341ef639e6fSAlexey Brodkin aux = ARC_AUX_DC_FLSH; 342ef639e6fSAlexey Brodkin 343ef639e6fSAlexey Brodkin write_aux_reg(aux, 0x1); 344ef639e6fSAlexey Brodkin 345ef639e6fSAlexey Brodkin __after_dc_op(cacheop, ctrl_reg); 346ef639e6fSAlexey Brodkin } 347ef639e6fSAlexey Brodkin 348ef639e6fSAlexey Brodkin static inline void __dc_line_op(unsigned long paddr, unsigned long sz, 349ef639e6fSAlexey Brodkin const int cacheop) 350ef639e6fSAlexey Brodkin { 351ef639e6fSAlexey Brodkin unsigned int ctrl_reg = __before_dc_op(cacheop); 352ef639e6fSAlexey Brodkin __cache_line_loop(paddr, sz, cacheop); 353ef639e6fSAlexey Brodkin __after_dc_op(cacheop, ctrl_reg); 354ef639e6fSAlexey Brodkin } 355ef639e6fSAlexey Brodkin #else 356ef639e6fSAlexey Brodkin #define __dc_entire_op(cacheop) 357ef639e6fSAlexey Brodkin #define __dc_line_op(paddr, sz, cacheop) 358ef639e6fSAlexey Brodkin #endif /* !CONFIG_SYS_DCACHE_OFF */ 359ef639e6fSAlexey Brodkin 360660d5f0dSAlexey Brodkin void invalidate_dcache_range(unsigned long start, unsigned long end) 361660d5f0dSAlexey Brodkin { 362ef639e6fSAlexey Brodkin __dc_line_op(start, end - start, OP_INV); 363ef639e6fSAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 364ef639e6fSAlexey Brodkin if (slc_exists) 365ef639e6fSAlexey Brodkin __slc_line_op(start, end - start, OP_INV); 366660d5f0dSAlexey Brodkin #endif 367660d5f0dSAlexey Brodkin } 368660d5f0dSAlexey Brodkin 369ef639e6fSAlexey Brodkin void flush_dcache_range(unsigned long start, unsigned long end) 370660d5f0dSAlexey Brodkin { 371ef639e6fSAlexey Brodkin __dc_line_op(start, end - start, OP_FLUSH); 372ef639e6fSAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 373ef639e6fSAlexey Brodkin if (slc_exists) 374ef639e6fSAlexey Brodkin __slc_line_op(start, end - start, OP_FLUSH); 375ef639e6fSAlexey Brodkin #endif 376660d5f0dSAlexey Brodkin } 377660d5f0dSAlexey Brodkin 378660d5f0dSAlexey Brodkin void flush_cache(unsigned long start, unsigned long size) 379660d5f0dSAlexey Brodkin { 380660d5f0dSAlexey Brodkin flush_dcache_range(start, start + size); 381660d5f0dSAlexey Brodkin } 3826eb15e50SAlexey Brodkin 383ef639e6fSAlexey Brodkin void invalidate_dcache_all(void) 384ef639e6fSAlexey Brodkin { 385ef639e6fSAlexey Brodkin __dc_entire_op(OP_INV); 3866eb15e50SAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 387ef639e6fSAlexey Brodkin if (slc_exists) 388ef639e6fSAlexey Brodkin __slc_entire_op(OP_INV); 389ef639e6fSAlexey Brodkin #endif 3906eb15e50SAlexey Brodkin } 3916eb15e50SAlexey Brodkin 392ef639e6fSAlexey Brodkin void flush_dcache_all(void) 3936eb15e50SAlexey Brodkin { 394ef639e6fSAlexey Brodkin __dc_entire_op(OP_FLUSH); 395ef639e6fSAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 396ef639e6fSAlexey Brodkin if (slc_exists) 397ef639e6fSAlexey Brodkin __slc_entire_op(OP_FLUSH); 398ef639e6fSAlexey Brodkin #endif 3996eb15e50SAlexey Brodkin } 400