1 /* 2 * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <config.h> 8 #include <asm/arcregs.h> 9 #include <asm/cache.h> 10 11 /* Bit values in IC_CTRL */ 12 #define IC_CTRL_CACHE_DISABLE (1 << 0) 13 14 /* Bit values in DC_CTRL */ 15 #define DC_CTRL_CACHE_DISABLE (1 << 0) 16 #define DC_CTRL_INV_MODE_FLUSH (1 << 6) 17 #define DC_CTRL_FLUSH_STATUS (1 << 8) 18 #define CACHE_VER_NUM_MASK 0xF 19 #define SLC_CTRL_SB (1 << 2) 20 21 int icache_status(void) 22 { 23 /* If no cache in CPU exit immediately */ 24 if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) 25 return 0; 26 27 return (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE) != 28 IC_CTRL_CACHE_DISABLE; 29 } 30 31 void icache_enable(void) 32 { 33 /* If no cache in CPU exit immediately */ 34 if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) 35 return; 36 37 write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) & 38 ~IC_CTRL_CACHE_DISABLE); 39 } 40 41 void icache_disable(void) 42 { 43 /* If no cache in CPU exit immediately */ 44 if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) 45 return; 46 47 write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) | 48 IC_CTRL_CACHE_DISABLE); 49 } 50 51 void invalidate_icache_all(void) 52 { 53 /* If no cache in CPU exit immediately */ 54 if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) 55 return; 56 57 /* Any write to IC_IVIC register triggers invalidation of entire I$ */ 58 write_aux_reg(ARC_AUX_IC_IVIC, 1); 59 } 60 61 int dcache_status(void) 62 { 63 /* If no cache in CPU exit immediately */ 64 if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 65 return 0; 66 67 return (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) != 68 DC_CTRL_CACHE_DISABLE; 69 } 70 71 void dcache_enable(void) 72 { 73 /* If no cache in CPU exit immediately */ 74 if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 75 return; 76 77 write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) & 78 ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE)); 79 } 80 81 void dcache_disable(void) 82 { 83 /* If no cache in CPU exit immediately */ 84 if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 85 return; 86 87 write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) | 88 DC_CTRL_CACHE_DISABLE); 89 } 90 91 void flush_dcache_all(void) 92 { 93 /* If no cache in CPU exit immediately */ 94 if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 95 return; 96 97 /* Do flush of entire cache */ 98 write_aux_reg(ARC_AUX_DC_FLSH, 1); 99 100 /* Wait flush end */ 101 while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) 102 ; 103 } 104 105 #ifndef CONFIG_SYS_DCACHE_OFF 106 static void dcache_flush_line(unsigned addr) 107 { 108 #if (CONFIG_ARC_MMU_VER == 3) 109 write_aux_reg(ARC_AUX_DC_PTAG, addr); 110 #endif 111 write_aux_reg(ARC_AUX_DC_FLDL, addr); 112 113 /* Wait flush end */ 114 while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) 115 ; 116 117 #ifndef CONFIG_SYS_ICACHE_OFF 118 /* 119 * Invalidate I$ for addresses range just flushed from D$. 120 * If we try to execute data flushed above it will be valid/correct 121 */ 122 #if (CONFIG_ARC_MMU_VER == 3) 123 write_aux_reg(ARC_AUX_IC_PTAG, addr); 124 #endif 125 write_aux_reg(ARC_AUX_IC_IVIL, addr); 126 #endif /* CONFIG_SYS_ICACHE_OFF */ 127 } 128 #endif /* CONFIG_SYS_DCACHE_OFF */ 129 130 void flush_dcache_range(unsigned long start, unsigned long end) 131 { 132 #ifndef CONFIG_SYS_DCACHE_OFF 133 unsigned int addr; 134 135 start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 136 end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 137 138 for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) 139 dcache_flush_line(addr); 140 #endif /* CONFIG_SYS_DCACHE_OFF */ 141 } 142 143 void invalidate_dcache_range(unsigned long start, unsigned long end) 144 { 145 #ifndef CONFIG_SYS_DCACHE_OFF 146 unsigned int addr; 147 148 start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 149 end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 150 151 for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) { 152 #if (CONFIG_ARC_MMU_VER == 3) 153 write_aux_reg(ARC_AUX_DC_PTAG, addr); 154 #endif 155 write_aux_reg(ARC_AUX_DC_IVDL, addr); 156 } 157 #endif /* CONFIG_SYS_DCACHE_OFF */ 158 } 159 160 void invalidate_dcache_all(void) 161 { 162 /* If no cache in CPU exit immediately */ 163 if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 164 return; 165 166 /* Write 1 to DC_IVDC register triggers invalidation of entire D$ */ 167 write_aux_reg(ARC_AUX_DC_IVDC, 1); 168 } 169 170 void flush_cache(unsigned long start, unsigned long size) 171 { 172 flush_dcache_range(start, start + size); 173 } 174 175 #ifdef CONFIG_ISA_ARCV2 176 void slc_enable(void) 177 { 178 /* If SLC ver = 0, no SLC present in CPU */ 179 if (!(read_aux_reg(ARC_BCR_SLC) & 0xff)) 180 return; 181 182 write_aux_reg(ARC_AUX_SLC_CONTROL, 183 read_aux_reg(ARC_AUX_SLC_CONTROL) & ~1); 184 } 185 186 void slc_disable(void) 187 { 188 /* If SLC ver = 0, no SLC present in CPU */ 189 if (!(read_aux_reg(ARC_BCR_SLC) & 0xff)) 190 return; 191 192 write_aux_reg(ARC_AUX_SLC_CONTROL, 193 read_aux_reg(ARC_AUX_SLC_CONTROL) | 1); 194 } 195 196 void slc_flush(void) 197 { 198 /* If SLC ver = 0, no SLC present in CPU */ 199 if (!(read_aux_reg(ARC_BCR_SLC) & 0xff)) 200 return; 201 202 write_aux_reg(ARC_AUX_SLC_FLUSH, 1); 203 204 /* Wait flush end */ 205 while (read_aux_reg(ARC_AUX_SLC_CONTROL) & SLC_CTRL_SB) 206 ; 207 } 208 209 void slc_invalidate(void) 210 { 211 /* If SLC ver = 0, no SLC present in CPU */ 212 if (!(read_aux_reg(ARC_BCR_SLC) & 0xff)) 213 return; 214 215 write_aux_reg(ARC_AUX_SLC_INVALIDATE, 1); 216 } 217 218 #endif /* CONFIG_ISA_ARCV2 */ 219