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 CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR 104 __asm__ __volatile__ (" \ 105 msrclr r0, %0; \ 106 nop; " \ 107 : \ 108 : "i" (MSR_DCE) \ 109 : "memory"); 110 #else 111 __asm__ __volatile__ (" \ 112 mfs r12, rmsr; \ 113 nop; \ 114 andi r12, r12, ~%0; \ 115 mts rmsr, r12; \ 116 nop; " \ 117 : \ 118 : "i" (MSR_DCE) \ 119 : "memory", "r12"); 120 #endif 121 } 122 123 void _invalidate_dcache(unsigned int addr) 124 { 125 __asm__ __volatile__ (" \ 126 wdc %0, r0" \ 127 : \ 128 : "r" (addr)); 129 } 130 131 void __invalidate_icache_all(void) 132 { 133 unsigned int i; 134 unsigned flags; 135 136 if (cpuinfo.use_icache) { 137 local_irq_save(flags); 138 __disable_icache(); 139 140 /* Just loop through cache size and invalidate, no need to add 141 CACHE_BASE address */ 142 for (i = 0; i < cpuinfo.icache_size; 143 i += cpuinfo.icache_line) 144 __invalidate_icache(i); 145 146 __enable_icache(); 147 local_irq_restore(flags); 148 } 149 } 150 151 void __invalidate_icache_range(unsigned long start, unsigned long end) 152 { 153 unsigned int i; 154 unsigned flags; 155 unsigned int align; 156 157 if (cpuinfo.use_icache) { 158 /* 159 * No need to cover entire cache range, 160 * just cover cache footprint 161 */ 162 end = min(start + cpuinfo.icache_size, end); 163 align = ~(cpuinfo.icache_line - 1); 164 start &= align; /* Make sure we are aligned */ 165 /* Push end up to the next cache line */ 166 end = ((end & align) + cpuinfo.icache_line); 167 168 local_irq_save(flags); 169 __disable_icache(); 170 171 for (i = start; i < end; i += cpuinfo.icache_line) 172 __invalidate_icache(i); 173 174 __enable_icache(); 175 local_irq_restore(flags); 176 } 177 } 178 179 void __invalidate_icache_page(struct vm_area_struct *vma, struct page *page) 180 { 181 __invalidate_icache_all(); 182 } 183 184 void __invalidate_icache_user_range(struct vm_area_struct *vma, 185 struct page *page, unsigned long adr, 186 int len) 187 { 188 __invalidate_icache_all(); 189 } 190 191 void __invalidate_cache_sigtramp(unsigned long addr) 192 { 193 __invalidate_icache_range(addr, addr + 8); 194 } 195 196 void __invalidate_dcache_all(void) 197 { 198 unsigned int i; 199 unsigned flags; 200 201 if (cpuinfo.use_dcache) { 202 local_irq_save(flags); 203 __disable_dcache(); 204 205 /* 206 * Just loop through cache size and invalidate, 207 * no need to add CACHE_BASE address 208 */ 209 for (i = 0; i < cpuinfo.dcache_size; 210 i += cpuinfo.dcache_line) 211 __invalidate_dcache(i); 212 213 __enable_dcache(); 214 local_irq_restore(flags); 215 } 216 } 217 218 void __invalidate_dcache_range(unsigned long start, unsigned long end) 219 { 220 unsigned int i; 221 unsigned flags; 222 unsigned int align; 223 224 if (cpuinfo.use_dcache) { 225 /* 226 * No need to cover entire cache range, 227 * just cover cache footprint 228 */ 229 end = min(start + cpuinfo.dcache_size, end); 230 align = ~(cpuinfo.dcache_line - 1); 231 start &= align; /* Make sure we are aligned */ 232 /* Push end up to the next cache line */ 233 end = ((end & align) + cpuinfo.dcache_line); 234 local_irq_save(flags); 235 __disable_dcache(); 236 237 for (i = start; i < end; i += cpuinfo.dcache_line) 238 __invalidate_dcache(i); 239 240 __enable_dcache(); 241 local_irq_restore(flags); 242 } 243 } 244 245 void __invalidate_dcache_page(struct vm_area_struct *vma, struct page *page) 246 { 247 __invalidate_dcache_all(); 248 } 249 250 void __invalidate_dcache_user_range(struct vm_area_struct *vma, 251 struct page *page, unsigned long adr, 252 int len) 253 { 254 __invalidate_dcache_all(); 255 } 256