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 10 /* Bit values in IC_CTRL */ 11 #define IC_CTRL_CACHE_DISABLE (1 << 0) 12 13 /* Bit values in DC_CTRL */ 14 #define DC_CTRL_CACHE_DISABLE (1 << 0) 15 #define DC_CTRL_INV_MODE_FLUSH (1 << 6) 16 #define DC_CTRL_FLUSH_STATUS (1 << 8) 17 #define CACHE_VER_NUM_MASK 0xF 18 19 int icache_status(void) 20 { 21 /* If no cache in CPU exit immediately */ 22 if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) 23 return 0; 24 25 return (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE) != 26 IC_CTRL_CACHE_DISABLE; 27 } 28 29 void icache_enable(void) 30 { 31 /* If no cache in CPU exit immediately */ 32 if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) 33 return; 34 35 write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) & 36 ~IC_CTRL_CACHE_DISABLE); 37 } 38 39 void icache_disable(void) 40 { 41 /* If no cache in CPU exit immediately */ 42 if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) 43 return; 44 45 write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) | 46 IC_CTRL_CACHE_DISABLE); 47 } 48 49 void invalidate_icache_all(void) 50 { 51 #ifndef CONFIG_SYS_ICACHE_OFF 52 /* Any write to IC_IVIC register triggers invalidation of entire I$ */ 53 write_aux_reg(ARC_AUX_IC_IVIC, 1); 54 #endif /* CONFIG_SYS_ICACHE_OFF */ 55 } 56 57 int dcache_status(void) 58 { 59 /* If no cache in CPU exit immediately */ 60 if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 61 return 0; 62 63 return (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) != 64 DC_CTRL_CACHE_DISABLE; 65 } 66 67 void dcache_enable(void) 68 { 69 /* If no cache in CPU exit immediately */ 70 if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 71 return; 72 73 write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) & 74 ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE)); 75 } 76 77 void dcache_disable(void) 78 { 79 /* If no cache in CPU exit immediately */ 80 if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 81 return; 82 83 write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) | 84 DC_CTRL_CACHE_DISABLE); 85 } 86 87 void flush_dcache_all(void) 88 { 89 /* If no cache in CPU exit immediately */ 90 if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 91 return; 92 93 /* Do flush of entire cache */ 94 write_aux_reg(ARC_AUX_DC_FLSH, 1); 95 96 /* Wait flush end */ 97 while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) 98 ; 99 } 100 101 #ifndef CONFIG_SYS_DCACHE_OFF 102 static void dcache_flush_line(unsigned addr) 103 { 104 #if (CONFIG_ARC_MMU_VER > 2) 105 write_aux_reg(ARC_AUX_DC_PTAG, addr); 106 #endif 107 write_aux_reg(ARC_AUX_DC_FLDL, addr); 108 109 /* Wait flush end */ 110 while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) 111 ; 112 113 #ifndef CONFIG_SYS_ICACHE_OFF 114 /* 115 * Invalidate I$ for addresses range just flushed from D$. 116 * If we try to execute data flushed above it will be valid/correct 117 */ 118 #if (CONFIG_ARC_MMU_VER > 2) 119 write_aux_reg(ARC_AUX_IC_PTAG, addr); 120 #endif 121 write_aux_reg(ARC_AUX_IC_IVIL, addr); 122 #endif /* CONFIG_SYS_ICACHE_OFF */ 123 } 124 #endif /* CONFIG_SYS_DCACHE_OFF */ 125 126 void flush_dcache_range(unsigned long start, unsigned long end) 127 { 128 #ifndef CONFIG_SYS_DCACHE_OFF 129 unsigned int addr; 130 131 start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 132 end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 133 134 for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) 135 dcache_flush_line(addr); 136 #endif /* CONFIG_SYS_DCACHE_OFF */ 137 } 138 139 void invalidate_dcache_range(unsigned long start, unsigned long end) 140 { 141 #ifndef CONFIG_SYS_DCACHE_OFF 142 unsigned int addr; 143 144 start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 145 end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 146 147 for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) { 148 #if (CONFIG_ARC_MMU_VER > 2) 149 write_aux_reg(ARC_AUX_DC_PTAG, addr); 150 #endif 151 write_aux_reg(ARC_AUX_DC_IVDL, addr); 152 } 153 #endif /* CONFIG_SYS_DCACHE_OFF */ 154 } 155 156 void invalidate_dcache_all(void) 157 { 158 #ifndef CONFIG_SYS_DCACHE_OFF 159 /* Write 1 to DC_IVDC register triggers invalidation of entire D$ */ 160 write_aux_reg(ARC_AUX_DC_IVDC, 1); 161 #endif /* CONFIG_SYS_DCACHE_OFF */ 162 } 163 164 void flush_cache(unsigned long start, unsigned long size) 165 { 166 flush_dcache_range(start, start + size); 167 } 168