1 /* 2 * Cache control for MicroBlaze cache memories 3 * 4 * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> 5 * Copyright (C) 2007-2009 PetaLogix 6 * Copyright (C) 2007 John Williams <john.williams@petalogix.com> 7 * 8 * This file is subject to the terms and conditions of the GNU General 9 * Public License. See the file COPYING in the main directory of this 10 * archive for more details. 11 */ 12 13 #include <asm/cacheflush.h> 14 #include <linux/cache.h> 15 #include <asm/cpuinfo.h> 16 17 /* Exported functions */ 18 19 void _enable_icache(void) 20 { 21 if (cpuinfo.use_icache) { 22 #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR 23 __asm__ __volatile__ (" \ 24 msrset r0, %0; \ 25 nop; " \ 26 : \ 27 : "i" (MSR_ICE) \ 28 : "memory"); 29 #else 30 __asm__ __volatile__ (" \ 31 mfs r12, rmsr; \ 32 nop; \ 33 ori r12, r12, %0; \ 34 mts rmsr, r12; \ 35 nop; " \ 36 : \ 37 : "i" (MSR_ICE) \ 38 : "memory", "r12"); 39 #endif 40 } 41 } 42 43 void _disable_icache(void) 44 { 45 if (cpuinfo.use_icache) { 46 #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR 47 __asm__ __volatile__ (" \ 48 msrclr r0, %0; \ 49 nop; " \ 50 : \ 51 : "i" (MSR_ICE) \ 52 : "memory"); 53 #else 54 __asm__ __volatile__ (" \ 55 mfs r12, rmsr; \ 56 nop; \ 57 andi r12, r12, ~%0; \ 58 mts rmsr, r12; \ 59 nop; " \ 60 : \ 61 : "i" (MSR_ICE) \ 62 : "memory", "r12"); 63 #endif 64 } 65 } 66 67 void _invalidate_icache(unsigned int addr) 68 { 69 if (cpuinfo.use_icache) { 70 __asm__ __volatile__ (" \ 71 wic %0, r0" \ 72 : \ 73 : "r" (addr)); 74 } 75 } 76 77 void _enable_dcache(void) 78 { 79 if (cpuinfo.use_dcache) { 80 #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR 81 __asm__ __volatile__ (" \ 82 msrset r0, %0; \ 83 nop; " \ 84 : \ 85 : "i" (MSR_DCE) \ 86 : "memory"); 87 #else 88 __asm__ __volatile__ (" \ 89 mfs r12, rmsr; \ 90 nop; \ 91 ori r12, r12, %0; \ 92 mts rmsr, r12; \ 93 nop; " \ 94 : \ 95 : "i" (MSR_DCE) \ 96 : "memory", "r12"); 97 #endif 98 } 99 } 100 101 void _disable_dcache(void) 102 { 103 if (cpuinfo.use_dcache) { 104 #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR 105 __asm__ __volatile__ (" \ 106 msrclr r0, %0; \ 107 nop; " \ 108 : \ 109 : "i" (MSR_DCE) \ 110 : "memory"); 111 #else 112 __asm__ __volatile__ (" \ 113 mfs r12, rmsr; \ 114 nop; \ 115 andi r12, r12, ~%0; \ 116 mts rmsr, r12; \ 117 nop; " \ 118 : \ 119 : "i" (MSR_DCE) \ 120 : "memory", "r12"); 121 #endif 122 } 123 } 124 125 void _invalidate_dcache(unsigned int addr) 126 { 127 if (cpuinfo.use_dcache) 128 __asm__ __volatile__ (" \ 129 wdc %0, r0" \ 130 : \ 131 : "r" (addr)); 132 } 133 134 void __invalidate_icache_all(void) 135 { 136 unsigned int i; 137 unsigned flags; 138 139 if (cpuinfo.use_icache) { 140 local_irq_save(flags); 141 __disable_icache(); 142 143 /* Just loop through cache size and invalidate, no need to add 144 CACHE_BASE address */ 145 for (i = 0; i < cpuinfo.icache_size; 146 i += cpuinfo.icache_line) 147 __invalidate_icache(i); 148 149 __enable_icache(); 150 local_irq_restore(flags); 151 } 152 } 153 154 void __invalidate_icache_range(unsigned long start, unsigned long end) 155 { 156 unsigned int i; 157 unsigned flags; 158 unsigned int align; 159 160 if (cpuinfo.use_icache) { 161 /* 162 * No need to cover entire cache range, 163 * just cover cache footprint 164 */ 165 end = min(start + cpuinfo.icache_size, end); 166 align = ~(cpuinfo.icache_line - 1); 167 start &= align; /* Make sure we are aligned */ 168 /* Push end up to the next cache line */ 169 end = ((end & align) + cpuinfo.icache_line); 170 171 local_irq_save(flags); 172 __disable_icache(); 173 174 for (i = start; i < end; i += cpuinfo.icache_line) 175 __invalidate_icache(i); 176 177 __enable_icache(); 178 local_irq_restore(flags); 179 } 180 } 181 182 void __invalidate_icache_page(struct vm_area_struct *vma, struct page *page) 183 { 184 __invalidate_icache_all(); 185 } 186 187 void __invalidate_icache_user_range(struct vm_area_struct *vma, 188 struct page *page, unsigned long adr, 189 int len) 190 { 191 __invalidate_icache_all(); 192 } 193 194 void __invalidate_cache_sigtramp(unsigned long addr) 195 { 196 __invalidate_icache_range(addr, addr + 8); 197 } 198 199 void __invalidate_dcache_all(void) 200 { 201 unsigned int i; 202 unsigned flags; 203 204 if (cpuinfo.use_dcache) { 205 local_irq_save(flags); 206 __disable_dcache(); 207 208 /* 209 * Just loop through cache size and invalidate, 210 * no need to add CACHE_BASE address 211 */ 212 for (i = 0; i < cpuinfo.dcache_size; 213 i += cpuinfo.dcache_line) 214 __invalidate_dcache(i); 215 216 __enable_dcache(); 217 local_irq_restore(flags); 218 } 219 } 220 221 void __invalidate_dcache_range(unsigned long start, unsigned long end) 222 { 223 unsigned int i; 224 unsigned flags; 225 unsigned int align; 226 227 if (cpuinfo.use_dcache) { 228 /* 229 * No need to cover entire cache range, 230 * just cover cache footprint 231 */ 232 end = min(start + cpuinfo.dcache_size, end); 233 align = ~(cpuinfo.dcache_line - 1); 234 start &= align; /* Make sure we are aligned */ 235 /* Push end up to the next cache line */ 236 end = ((end & align) + cpuinfo.dcache_line); 237 local_irq_save(flags); 238 __disable_dcache(); 239 240 for (i = start; i < end; i += cpuinfo.dcache_line) 241 __invalidate_dcache(i); 242 243 __enable_dcache(); 244 local_irq_restore(flags); 245 } 246 } 247 248 void __invalidate_dcache_page(struct vm_area_struct *vma, struct page *page) 249 { 250 __invalidate_dcache_all(); 251 } 252 253 void __invalidate_dcache_user_range(struct vm_area_struct *vma, 254 struct page *page, unsigned long adr, 255 int len) 256 { 257 __invalidate_dcache_all(); 258 } 259