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> 8379b3280SAlexey 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 */ 33379b3280SAlexey Brodkin int l1_line_sz __section(".data"); 34379b3280SAlexey Brodkin int dcache_exists __section(".data"); 35379b3280SAlexey Brodkin int icache_exists __section(".data"); 36379b3280SAlexey Brodkin 37379b3280SAlexey Brodkin #define CACHE_LINE_MASK (~(l1_line_sz - 1)) 38379b3280SAlexey Brodkin 39379b3280SAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 40ef639e6fSAlexey Brodkin int slc_line_sz __section(".data"); 41ef639e6fSAlexey Brodkin int slc_exists __section(".data"); 42*db6ce231SAlexey Brodkin int ioc_exists __section(".data"); 43ef639e6fSAlexey Brodkin 44ef639e6fSAlexey Brodkin static unsigned int __before_slc_op(const int op) 45ef639e6fSAlexey Brodkin { 46ef639e6fSAlexey Brodkin unsigned int reg = reg; 47ef639e6fSAlexey Brodkin 48ef639e6fSAlexey Brodkin if (op == OP_INV) { 49ef639e6fSAlexey Brodkin /* 50ef639e6fSAlexey Brodkin * IM is set by default and implies Flush-n-inv 51ef639e6fSAlexey Brodkin * Clear it here for vanilla inv 52ef639e6fSAlexey Brodkin */ 53ef639e6fSAlexey Brodkin reg = read_aux_reg(ARC_AUX_SLC_CTRL); 54ef639e6fSAlexey Brodkin write_aux_reg(ARC_AUX_SLC_CTRL, reg & ~DC_CTRL_INV_MODE_FLUSH); 55ef639e6fSAlexey Brodkin } 56ef639e6fSAlexey Brodkin 57ef639e6fSAlexey Brodkin return reg; 58ef639e6fSAlexey Brodkin } 59ef639e6fSAlexey Brodkin 60ef639e6fSAlexey Brodkin static void __after_slc_op(const int op, unsigned int reg) 61ef639e6fSAlexey Brodkin { 62ef639e6fSAlexey Brodkin if (op & OP_FLUSH) /* flush / flush-n-inv both wait */ 63ef639e6fSAlexey Brodkin while (read_aux_reg(ARC_AUX_SLC_CTRL) & 64ef639e6fSAlexey Brodkin DC_CTRL_FLUSH_STATUS) 65ef639e6fSAlexey Brodkin ; 66ef639e6fSAlexey Brodkin 67ef639e6fSAlexey Brodkin /* Switch back to default Invalidate mode */ 68ef639e6fSAlexey Brodkin if (op == OP_INV) 69ef639e6fSAlexey Brodkin write_aux_reg(ARC_AUX_SLC_CTRL, reg | DC_CTRL_INV_MODE_FLUSH); 70ef639e6fSAlexey Brodkin } 71ef639e6fSAlexey Brodkin 72ef639e6fSAlexey Brodkin static inline void __slc_line_loop(unsigned long paddr, unsigned long sz, 73ef639e6fSAlexey Brodkin const int op) 74ef639e6fSAlexey Brodkin { 75ef639e6fSAlexey Brodkin unsigned int aux_cmd; 76ef639e6fSAlexey Brodkin int num_lines; 77ef639e6fSAlexey Brodkin 78ef639e6fSAlexey Brodkin #define SLC_LINE_MASK (~(slc_line_sz - 1)) 79ef639e6fSAlexey Brodkin 80ef639e6fSAlexey Brodkin aux_cmd = op & OP_INV ? ARC_AUX_SLC_IVDL : ARC_AUX_SLC_FLDL; 81ef639e6fSAlexey Brodkin 82ef639e6fSAlexey Brodkin sz += paddr & ~SLC_LINE_MASK; 83ef639e6fSAlexey Brodkin paddr &= SLC_LINE_MASK; 84ef639e6fSAlexey Brodkin 85ef639e6fSAlexey Brodkin num_lines = DIV_ROUND_UP(sz, slc_line_sz); 86ef639e6fSAlexey Brodkin 87ef639e6fSAlexey Brodkin while (num_lines-- > 0) { 88ef639e6fSAlexey Brodkin write_aux_reg(aux_cmd, paddr); 89ef639e6fSAlexey Brodkin paddr += slc_line_sz; 90ef639e6fSAlexey Brodkin } 91ef639e6fSAlexey Brodkin } 92ef639e6fSAlexey Brodkin 93ef639e6fSAlexey Brodkin static inline void __slc_entire_op(const int cacheop) 94ef639e6fSAlexey Brodkin { 95ef639e6fSAlexey Brodkin int aux; 96ef639e6fSAlexey Brodkin unsigned int ctrl_reg = __before_slc_op(cacheop); 97ef639e6fSAlexey Brodkin 98ef639e6fSAlexey Brodkin if (cacheop & OP_INV) /* Inv or flush-n-inv use same cmd reg */ 99ef639e6fSAlexey Brodkin aux = ARC_AUX_SLC_INVALIDATE; 100ef639e6fSAlexey Brodkin else 101ef639e6fSAlexey Brodkin aux = ARC_AUX_SLC_FLUSH; 102ef639e6fSAlexey Brodkin 103ef639e6fSAlexey Brodkin write_aux_reg(aux, 0x1); 104ef639e6fSAlexey Brodkin 105ef639e6fSAlexey Brodkin __after_slc_op(cacheop, ctrl_reg); 106ef639e6fSAlexey Brodkin } 107ef639e6fSAlexey Brodkin 108ef639e6fSAlexey Brodkin static inline void __slc_line_op(unsigned long paddr, unsigned long sz, 109ef639e6fSAlexey Brodkin const int cacheop) 110ef639e6fSAlexey Brodkin { 111ef639e6fSAlexey Brodkin unsigned int ctrl_reg = __before_slc_op(cacheop); 112ef639e6fSAlexey Brodkin __slc_line_loop(paddr, sz, cacheop); 113ef639e6fSAlexey Brodkin __after_slc_op(cacheop, ctrl_reg); 114ef639e6fSAlexey Brodkin } 115ef639e6fSAlexey Brodkin #else 116ef639e6fSAlexey Brodkin #define __slc_entire_op(cacheop) 117ef639e6fSAlexey Brodkin #define __slc_line_op(paddr, sz, cacheop) 118ef639e6fSAlexey Brodkin #endif 119ef639e6fSAlexey Brodkin 120379b3280SAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 121379b3280SAlexey Brodkin static void read_decode_cache_bcr_arcv2(void) 122ef639e6fSAlexey Brodkin { 123379b3280SAlexey Brodkin union { 124379b3280SAlexey Brodkin struct { 125379b3280SAlexey Brodkin #ifdef CONFIG_CPU_BIG_ENDIAN 126379b3280SAlexey Brodkin unsigned int pad:24, way:2, lsz:2, sz:4; 127379b3280SAlexey Brodkin #else 128379b3280SAlexey Brodkin unsigned int sz:4, lsz:2, way:2, pad:24; 129379b3280SAlexey Brodkin #endif 130379b3280SAlexey Brodkin } fields; 131379b3280SAlexey Brodkin unsigned int word; 132379b3280SAlexey Brodkin } slc_cfg; 133379b3280SAlexey Brodkin 134379b3280SAlexey Brodkin union { 135379b3280SAlexey Brodkin struct { 136379b3280SAlexey Brodkin #ifdef CONFIG_CPU_BIG_ENDIAN 137379b3280SAlexey Brodkin unsigned int pad:24, ver:8; 138379b3280SAlexey Brodkin #else 139379b3280SAlexey Brodkin unsigned int ver:8, pad:24; 140379b3280SAlexey Brodkin #endif 141379b3280SAlexey Brodkin } fields; 142379b3280SAlexey Brodkin unsigned int word; 143379b3280SAlexey Brodkin } sbcr; 144379b3280SAlexey Brodkin 145379b3280SAlexey Brodkin sbcr.word = read_aux_reg(ARC_BCR_SLC); 146379b3280SAlexey Brodkin if (sbcr.fields.ver) { 147379b3280SAlexey Brodkin slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG); 148379b3280SAlexey Brodkin slc_exists = 1; 149379b3280SAlexey Brodkin slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64; 150379b3280SAlexey Brodkin } 151*db6ce231SAlexey Brodkin 152*db6ce231SAlexey Brodkin union { 153*db6ce231SAlexey Brodkin struct bcr_clust_cfg { 154*db6ce231SAlexey Brodkin #ifdef CONFIG_CPU_BIG_ENDIAN 155*db6ce231SAlexey Brodkin unsigned int pad:7, c:1, num_entries:8, num_cores:8, ver:8; 156*db6ce231SAlexey Brodkin #else 157*db6ce231SAlexey Brodkin unsigned int ver:8, num_cores:8, num_entries:8, c:1, pad:7; 158*db6ce231SAlexey Brodkin #endif 159*db6ce231SAlexey Brodkin } fields; 160*db6ce231SAlexey Brodkin unsigned int word; 161*db6ce231SAlexey Brodkin } cbcr; 162*db6ce231SAlexey Brodkin 163*db6ce231SAlexey Brodkin cbcr.word = read_aux_reg(ARC_BCR_CLUSTER); 164*db6ce231SAlexey Brodkin if (cbcr.fields.c) 165*db6ce231SAlexey Brodkin ioc_exists = 1; 166379b3280SAlexey Brodkin } 167379b3280SAlexey Brodkin #endif 168379b3280SAlexey Brodkin 169379b3280SAlexey Brodkin void read_decode_cache_bcr(void) 170379b3280SAlexey Brodkin { 171379b3280SAlexey Brodkin int dc_line_sz = 0, ic_line_sz = 0; 172379b3280SAlexey Brodkin 173379b3280SAlexey Brodkin union { 174379b3280SAlexey Brodkin struct { 175379b3280SAlexey Brodkin #ifdef CONFIG_CPU_BIG_ENDIAN 176379b3280SAlexey Brodkin unsigned int pad:12, line_len:4, sz:4, config:4, ver:8; 177379b3280SAlexey Brodkin #else 178379b3280SAlexey Brodkin unsigned int ver:8, config:4, sz:4, line_len:4, pad:12; 179379b3280SAlexey Brodkin #endif 180379b3280SAlexey Brodkin } fields; 181379b3280SAlexey Brodkin unsigned int word; 182379b3280SAlexey Brodkin } ibcr, dbcr; 183379b3280SAlexey Brodkin 184379b3280SAlexey Brodkin ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD); 185379b3280SAlexey Brodkin if (ibcr.fields.ver) { 186379b3280SAlexey Brodkin icache_exists = 1; 187379b3280SAlexey Brodkin l1_line_sz = ic_line_sz = 8 << ibcr.fields.line_len; 188379b3280SAlexey Brodkin if (!ic_line_sz) 189379b3280SAlexey Brodkin panic("Instruction exists but line length is 0\n"); 190ef639e6fSAlexey Brodkin } 191ef639e6fSAlexey Brodkin 192379b3280SAlexey Brodkin dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD); 193379b3280SAlexey Brodkin if (dbcr.fields.ver){ 194379b3280SAlexey Brodkin dcache_exists = 1; 195379b3280SAlexey Brodkin l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len; 196379b3280SAlexey Brodkin if (!dc_line_sz) 197379b3280SAlexey Brodkin panic("Data cache exists but line length is 0\n"); 198379b3280SAlexey Brodkin } 199379b3280SAlexey Brodkin 200379b3280SAlexey Brodkin if (ic_line_sz && dc_line_sz && (ic_line_sz != dc_line_sz)) 201379b3280SAlexey Brodkin panic("Instruction and data cache line lengths differ\n"); 202ef639e6fSAlexey Brodkin } 203ef639e6fSAlexey Brodkin 204ef639e6fSAlexey Brodkin void cache_init(void) 205ef639e6fSAlexey Brodkin { 206379b3280SAlexey Brodkin read_decode_cache_bcr(); 207379b3280SAlexey Brodkin 208ef639e6fSAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 209379b3280SAlexey Brodkin read_decode_cache_bcr_arcv2(); 210*db6ce231SAlexey Brodkin 211*db6ce231SAlexey Brodkin if (ioc_exists) { 212*db6ce231SAlexey Brodkin /* IO coherency base - 0x8z */ 213*db6ce231SAlexey Brodkin write_aux_reg(ARC_AUX_IO_COH_AP0_BASE, 0x80000); 214*db6ce231SAlexey Brodkin /* IO coherency aperture size - 512Mb: 0x8z-0xAz */ 215*db6ce231SAlexey Brodkin write_aux_reg(ARC_AUX_IO_COH_AP0_SIZE, 0x11); 216*db6ce231SAlexey Brodkin /* Enable partial writes */ 217*db6ce231SAlexey Brodkin write_aux_reg(ARC_AUX_IO_COH_PARTIAL, 1); 218*db6ce231SAlexey Brodkin /* Enable IO coherency */ 219*db6ce231SAlexey Brodkin write_aux_reg(ARC_AUX_IO_COH_ENABLE, 1); 220*db6ce231SAlexey Brodkin } 221ef639e6fSAlexey Brodkin #endif 222ef639e6fSAlexey Brodkin } 223ef639e6fSAlexey Brodkin 224660d5f0dSAlexey Brodkin int icache_status(void) 225660d5f0dSAlexey Brodkin { 226379b3280SAlexey Brodkin if (!icache_exists) 227660d5f0dSAlexey Brodkin return 0; 228660d5f0dSAlexey Brodkin 229ef639e6fSAlexey Brodkin if (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE) 230ef639e6fSAlexey Brodkin return 0; 231ef639e6fSAlexey Brodkin else 232ef639e6fSAlexey Brodkin return 1; 233660d5f0dSAlexey Brodkin } 234660d5f0dSAlexey Brodkin 235660d5f0dSAlexey Brodkin void icache_enable(void) 236660d5f0dSAlexey Brodkin { 237379b3280SAlexey Brodkin if (icache_exists) 238660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) & 239660d5f0dSAlexey Brodkin ~IC_CTRL_CACHE_DISABLE); 240660d5f0dSAlexey Brodkin } 241660d5f0dSAlexey Brodkin 242660d5f0dSAlexey Brodkin void icache_disable(void) 243660d5f0dSAlexey Brodkin { 244379b3280SAlexey Brodkin if (icache_exists) 245660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) | 246660d5f0dSAlexey Brodkin IC_CTRL_CACHE_DISABLE); 247660d5f0dSAlexey Brodkin } 248660d5f0dSAlexey Brodkin 249ef639e6fSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF 250660d5f0dSAlexey Brodkin void invalidate_icache_all(void) 251660d5f0dSAlexey Brodkin { 252660d5f0dSAlexey Brodkin /* Any write to IC_IVIC register triggers invalidation of entire I$ */ 253ef639e6fSAlexey Brodkin if (icache_status()) { 254660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_IVIC, 1); 255ef639e6fSAlexey Brodkin read_aux_reg(ARC_AUX_IC_CTRL); /* blocks */ 256660d5f0dSAlexey Brodkin } 257ef639e6fSAlexey Brodkin } 258ef639e6fSAlexey Brodkin #else 259ef639e6fSAlexey Brodkin void invalidate_icache_all(void) 260ef639e6fSAlexey Brodkin { 261ef639e6fSAlexey Brodkin } 262ef639e6fSAlexey Brodkin #endif 263660d5f0dSAlexey Brodkin 264660d5f0dSAlexey Brodkin int dcache_status(void) 265660d5f0dSAlexey Brodkin { 266379b3280SAlexey Brodkin if (!dcache_exists) 267660d5f0dSAlexey Brodkin return 0; 268660d5f0dSAlexey Brodkin 269ef639e6fSAlexey Brodkin if (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) 270ef639e6fSAlexey Brodkin return 0; 271ef639e6fSAlexey Brodkin else 272ef639e6fSAlexey Brodkin return 1; 273660d5f0dSAlexey Brodkin } 274660d5f0dSAlexey Brodkin 275660d5f0dSAlexey Brodkin void dcache_enable(void) 276660d5f0dSAlexey Brodkin { 277379b3280SAlexey Brodkin if (!dcache_exists) 278660d5f0dSAlexey Brodkin return; 279660d5f0dSAlexey Brodkin 280660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) & 281660d5f0dSAlexey Brodkin ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE)); 282660d5f0dSAlexey Brodkin } 283660d5f0dSAlexey Brodkin 284660d5f0dSAlexey Brodkin void dcache_disable(void) 285660d5f0dSAlexey Brodkin { 286379b3280SAlexey Brodkin if (!dcache_exists) 287660d5f0dSAlexey Brodkin return; 288660d5f0dSAlexey Brodkin 289660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) | 290660d5f0dSAlexey Brodkin DC_CTRL_CACHE_DISABLE); 291660d5f0dSAlexey Brodkin } 292660d5f0dSAlexey Brodkin 293660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF 294660d5f0dSAlexey Brodkin /* 295ef639e6fSAlexey Brodkin * Common Helper for Line Operations on {I,D}-Cache 296660d5f0dSAlexey Brodkin */ 297ef639e6fSAlexey Brodkin static inline void __cache_line_loop(unsigned long paddr, unsigned long sz, 298ef639e6fSAlexey Brodkin const int cacheop) 299660d5f0dSAlexey Brodkin { 300ef639e6fSAlexey Brodkin unsigned int aux_cmd; 301ef639e6fSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 302ef639e6fSAlexey Brodkin unsigned int aux_tag; 303ef639e6fSAlexey Brodkin #endif 304ef639e6fSAlexey Brodkin int num_lines; 305660d5f0dSAlexey Brodkin 306ef639e6fSAlexey Brodkin if (cacheop == OP_INV_IC) { 307ef639e6fSAlexey Brodkin aux_cmd = ARC_AUX_IC_IVIL; 308ef639e6fSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 309ef639e6fSAlexey Brodkin aux_tag = ARC_AUX_IC_PTAG; 310ef639e6fSAlexey Brodkin #endif 311ef639e6fSAlexey Brodkin } else { 312ef639e6fSAlexey Brodkin /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */ 313ef639e6fSAlexey Brodkin aux_cmd = cacheop & OP_INV ? ARC_AUX_DC_IVDL : ARC_AUX_DC_FLDL; 314ef639e6fSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 315ef639e6fSAlexey Brodkin aux_tag = ARC_AUX_DC_PTAG; 316ef639e6fSAlexey Brodkin #endif 317660d5f0dSAlexey Brodkin } 318660d5f0dSAlexey Brodkin 319ef639e6fSAlexey Brodkin sz += paddr & ~CACHE_LINE_MASK; 320ef639e6fSAlexey Brodkin paddr &= CACHE_LINE_MASK; 321ef639e6fSAlexey Brodkin 322379b3280SAlexey Brodkin num_lines = DIV_ROUND_UP(sz, l1_line_sz); 323ef639e6fSAlexey Brodkin 324ef639e6fSAlexey Brodkin while (num_lines-- > 0) { 325ef639e6fSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 326ef639e6fSAlexey Brodkin write_aux_reg(aux_tag, paddr); 327ef639e6fSAlexey Brodkin #endif 328ef639e6fSAlexey Brodkin write_aux_reg(aux_cmd, paddr); 329379b3280SAlexey Brodkin paddr += l1_line_sz; 330ef639e6fSAlexey Brodkin } 331ef639e6fSAlexey Brodkin } 332ef639e6fSAlexey Brodkin 333ef639e6fSAlexey Brodkin static unsigned int __before_dc_op(const int op) 334ef639e6fSAlexey Brodkin { 335ef639e6fSAlexey Brodkin unsigned int reg; 336ef639e6fSAlexey Brodkin 337ef639e6fSAlexey Brodkin if (op == OP_INV) { 338ef639e6fSAlexey Brodkin /* 339ef639e6fSAlexey Brodkin * IM is set by default and implies Flush-n-inv 340ef639e6fSAlexey Brodkin * Clear it here for vanilla inv 341ef639e6fSAlexey Brodkin */ 342ef639e6fSAlexey Brodkin reg = read_aux_reg(ARC_AUX_DC_CTRL); 343ef639e6fSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, reg & ~DC_CTRL_INV_MODE_FLUSH); 344ef639e6fSAlexey Brodkin } 345ef639e6fSAlexey Brodkin 346ef639e6fSAlexey Brodkin return reg; 347ef639e6fSAlexey Brodkin } 348ef639e6fSAlexey Brodkin 349ef639e6fSAlexey Brodkin static void __after_dc_op(const int op, unsigned int reg) 350ef639e6fSAlexey Brodkin { 351ef639e6fSAlexey Brodkin if (op & OP_FLUSH) /* flush / flush-n-inv both wait */ 352ef639e6fSAlexey Brodkin while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) 353ef639e6fSAlexey Brodkin ; 354ef639e6fSAlexey Brodkin 355ef639e6fSAlexey Brodkin /* Switch back to default Invalidate mode */ 356ef639e6fSAlexey Brodkin if (op == OP_INV) 357ef639e6fSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, reg | DC_CTRL_INV_MODE_FLUSH); 358ef639e6fSAlexey Brodkin } 359ef639e6fSAlexey Brodkin 360ef639e6fSAlexey Brodkin static inline void __dc_entire_op(const int cacheop) 361ef639e6fSAlexey Brodkin { 362ef639e6fSAlexey Brodkin int aux; 363ef639e6fSAlexey Brodkin unsigned int ctrl_reg = __before_dc_op(cacheop); 364ef639e6fSAlexey Brodkin 365ef639e6fSAlexey Brodkin if (cacheop & OP_INV) /* Inv or flush-n-inv use same cmd reg */ 366ef639e6fSAlexey Brodkin aux = ARC_AUX_DC_IVDC; 367ef639e6fSAlexey Brodkin else 368ef639e6fSAlexey Brodkin aux = ARC_AUX_DC_FLSH; 369ef639e6fSAlexey Brodkin 370ef639e6fSAlexey Brodkin write_aux_reg(aux, 0x1); 371ef639e6fSAlexey Brodkin 372ef639e6fSAlexey Brodkin __after_dc_op(cacheop, ctrl_reg); 373ef639e6fSAlexey Brodkin } 374ef639e6fSAlexey Brodkin 375ef639e6fSAlexey Brodkin static inline void __dc_line_op(unsigned long paddr, unsigned long sz, 376ef639e6fSAlexey Brodkin const int cacheop) 377ef639e6fSAlexey Brodkin { 378ef639e6fSAlexey Brodkin unsigned int ctrl_reg = __before_dc_op(cacheop); 379ef639e6fSAlexey Brodkin __cache_line_loop(paddr, sz, cacheop); 380ef639e6fSAlexey Brodkin __after_dc_op(cacheop, ctrl_reg); 381ef639e6fSAlexey Brodkin } 382ef639e6fSAlexey Brodkin #else 383ef639e6fSAlexey Brodkin #define __dc_entire_op(cacheop) 384ef639e6fSAlexey Brodkin #define __dc_line_op(paddr, sz, cacheop) 385ef639e6fSAlexey Brodkin #endif /* !CONFIG_SYS_DCACHE_OFF */ 386ef639e6fSAlexey Brodkin 387660d5f0dSAlexey Brodkin void invalidate_dcache_range(unsigned long start, unsigned long end) 388660d5f0dSAlexey Brodkin { 389ef639e6fSAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 390*db6ce231SAlexey Brodkin if (!ioc_exists) 391*db6ce231SAlexey Brodkin #endif 392*db6ce231SAlexey Brodkin __dc_line_op(start, end - start, OP_INV); 393*db6ce231SAlexey Brodkin 394*db6ce231SAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 395*db6ce231SAlexey Brodkin if (slc_exists && !ioc_exists) 396ef639e6fSAlexey Brodkin __slc_line_op(start, end - start, OP_INV); 397660d5f0dSAlexey Brodkin #endif 398660d5f0dSAlexey Brodkin } 399660d5f0dSAlexey Brodkin 400ef639e6fSAlexey Brodkin void flush_dcache_range(unsigned long start, unsigned long end) 401660d5f0dSAlexey Brodkin { 402ef639e6fSAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 403*db6ce231SAlexey Brodkin if (!ioc_exists) 404*db6ce231SAlexey Brodkin #endif 405*db6ce231SAlexey Brodkin __dc_line_op(start, end - start, OP_FLUSH); 406*db6ce231SAlexey Brodkin 407*db6ce231SAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 408*db6ce231SAlexey Brodkin if (slc_exists && !ioc_exists) 409ef639e6fSAlexey Brodkin __slc_line_op(start, end - start, OP_FLUSH); 410ef639e6fSAlexey Brodkin #endif 411660d5f0dSAlexey Brodkin } 412660d5f0dSAlexey Brodkin 413660d5f0dSAlexey Brodkin void flush_cache(unsigned long start, unsigned long size) 414660d5f0dSAlexey Brodkin { 415660d5f0dSAlexey Brodkin flush_dcache_range(start, start + size); 416660d5f0dSAlexey Brodkin } 4176eb15e50SAlexey Brodkin 418ef639e6fSAlexey Brodkin void invalidate_dcache_all(void) 419ef639e6fSAlexey Brodkin { 4206eb15e50SAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 421*db6ce231SAlexey Brodkin if (!ioc_exists) 422*db6ce231SAlexey Brodkin #endif 423*db6ce231SAlexey Brodkin __dc_entire_op(OP_INV); 424*db6ce231SAlexey Brodkin 425*db6ce231SAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 426*db6ce231SAlexey Brodkin if (slc_exists && !ioc_exists) 427ef639e6fSAlexey Brodkin __slc_entire_op(OP_INV); 428ef639e6fSAlexey Brodkin #endif 4296eb15e50SAlexey Brodkin } 4306eb15e50SAlexey Brodkin 431ef639e6fSAlexey Brodkin void flush_dcache_all(void) 4326eb15e50SAlexey Brodkin { 433ef639e6fSAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 434*db6ce231SAlexey Brodkin if (!ioc_exists) 435*db6ce231SAlexey Brodkin #endif 436*db6ce231SAlexey Brodkin __dc_entire_op(OP_FLUSH); 437*db6ce231SAlexey Brodkin 438*db6ce231SAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 439*db6ce231SAlexey Brodkin if (slc_exists && !ioc_exists) 440ef639e6fSAlexey Brodkin __slc_entire_op(OP_FLUSH); 441ef639e6fSAlexey Brodkin #endif 4426eb15e50SAlexey Brodkin } 443