1#include <config.h> 2#include <mpc86xx.h> 3 4#include <ppc_asm.tmpl> 5#include <ppc_defs.h> 6 7#include <asm/cache.h> 8#include <asm/mmu.h> 9 10#ifndef CACHE_LINE_SIZE 11# define CACHE_LINE_SIZE L1_CACHE_BYTES 12#endif 13 14#if CACHE_LINE_SIZE == 128 15#define LG_CACHE_LINE_SIZE 7 16#elif CACHE_LINE_SIZE == 32 17#define LG_CACHE_LINE_SIZE 5 18#elif CACHE_LINE_SIZE == 16 19#define LG_CACHE_LINE_SIZE 4 20#elif CACHE_LINE_SIZE == 8 21#define LG_CACHE_LINE_SIZE 3 22#else 23# error "Invalid cache line size!" 24#endif 25 26/* 27 * Most of this code is taken from 74xx_7xx/cache.S 28 * and then cleaned up a bit 29 */ 30 31/* 32 * Invalidate L1 instruction cache. 33 */ 34_GLOBAL(invalidate_l1_instruction_cache) 35 /* use invalidate-all bit in HID0 */ 36 mfspr r3,HID0 37 ori r3,r3,HID0_ICFI 38 mtspr HID0,r3 39 isync 40 blr 41 42/* 43 * Invalidate L1 data cache. 44 */ 45_GLOBAL(invalidate_l1_data_cache) 46 mfspr r3,HID0 47 ori r3,r3,HID0_DCFI 48 mtspr HID0,r3 49 isync 50 blr 51 52/* 53 * Flush data cache. 54 */ 55_GLOBAL(flush_dcache) 56 lis r3,0 57 lis r5,CACHE_LINE_SIZE 58flush: 59 cmp 0,1,r3,r5 60 bge done 61 lwz r5,0(r3) 62 lis r5,CACHE_LINE_SIZE 63 addi r3,r3,0x4 64 b flush 65done: 66 blr 67/* 68 * Write any modified data cache blocks out to memory 69 * and invalidate the corresponding instruction cache blocks. 70 * This is a no-op on the 601. 71 * 72 * flush_icache_range(unsigned long start, unsigned long stop) 73 */ 74_GLOBAL(flush_icache_range) 75 li r5,CACHE_LINE_SIZE-1 76 andc r3,r3,r5 77 subf r4,r3,r4 78 add r4,r4,r5 79 srwi. r4,r4,LG_CACHE_LINE_SIZE 80 beqlr 81 mtctr r4 82 mr r6,r3 831: dcbst 0,r3 84 addi r3,r3,CACHE_LINE_SIZE 85 bdnz 1b 86 sync /* wait for dcbst's to get to ram */ 87 mtctr r4 882: icbi 0,r6 89 addi r6,r6,CACHE_LINE_SIZE 90 bdnz 2b 91 sync /* additional sync needed on g4 */ 92 isync 93 blr 94/* 95 * Write any modified data cache blocks out to memory. 96 * Does not invalidate the corresponding cache lines (especially for 97 * any corresponding instruction cache). 98 * 99 * clean_dcache_range(unsigned long start, unsigned long stop) 100 */ 101_GLOBAL(clean_dcache_range) 102 li r5,CACHE_LINE_SIZE-1 103 andc r3,r3,r5 /* align r3 down to cache line */ 104 subf r4,r3,r4 /* r4 = offset of stop from start of cache line */ 105 add r4,r4,r5 /* r4 += cache_line_size-1 */ 106 srwi. r4,r4,LG_CACHE_LINE_SIZE /* r4 = number of cache lines to flush */ 107 beqlr /* if r4 == 0 return */ 108 mtctr r4 /* ctr = r4 */ 109 110 sync 1111: dcbst 0,r3 112 addi r3,r3,CACHE_LINE_SIZE 113 bdnz 1b 114 sync /* wait for dcbst's to get to ram */ 115 blr 116 117/* 118 * Flush a particular page from the data cache to RAM. 119 * Note: this is necessary because the instruction cache does *not* 120 * snoop from the data cache. 121 * 122 * void __flush_page_to_ram(void *page) 123 */ 124_GLOBAL(__flush_page_to_ram) 125 rlwinm r3,r3,0,0,19 /* Get page base address */ 126 li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */ 127 mtctr r4 128 mr r6,r3 1290: dcbst 0,r3 /* Write line to ram */ 130 addi r3,r3,CACHE_LINE_SIZE 131 bdnz 0b 132 sync 133 mtctr r4 1341: icbi 0,r6 135 addi r6,r6,CACHE_LINE_SIZE 136 bdnz 1b 137 sync 138 isync 139 blr 140 141/* 142 * Flush a particular page from the instruction cache. 143 * Note: this is necessary because the instruction cache does *not* 144 * snoop from the data cache. 145 * 146 * void __flush_icache_page(void *page) 147 */ 148_GLOBAL(__flush_icache_page) 149 li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */ 150 mtctr r4 1511: icbi 0,r3 152 addi r3,r3,CACHE_LINE_SIZE 153 bdnz 1b 154 sync 155 isync 156 blr 157 158/* 159 * Clear a page using the dcbz instruction, which doesn't cause any 160 * memory traffic (except to write out any cache lines which get 161 * displaced). This only works on cacheable memory. 162 */ 163_GLOBAL(clear_page) 164 li r0,4096/CACHE_LINE_SIZE 165 mtctr r0 1661: dcbz 0,r3 167 addi r3,r3,CACHE_LINE_SIZE 168 bdnz 1b 169 blr 170 171/* 172 * Enable L1 Instruction cache 173 */ 174_GLOBAL(icache_enable) 175 mfspr r3, HID0 176 li r5, HID0_ICFI|HID0_ILOCK 177 andc r3, r3, r5 178 ori r3, r3, HID0_ICE 179 ori r5, r3, HID0_ICFI 180 mtspr HID0, r5 181 mtspr HID0, r3 182 isync 183 blr 184 185/* 186 * Disable L1 Instruction cache 187 */ 188_GLOBAL(icache_disable) 189 mflr r4 190 bl invalidate_l1_instruction_cache /* uses r3 */ 191 sync 192 mtlr r4 193 mfspr r3, HID0 194 li r5, 0 195 ori r5, r5, HID0_ICE 196 andc r3, r3, r5 197 mtspr HID0, r3 198 isync 199 blr 200 201/* 202 * Is instruction cache enabled? 203 */ 204_GLOBAL(icache_status) 205 mfspr r3, HID0 206 andi. r3, r3, HID0_ICE 207 blr 208 209 210_GLOBAL(l1dcache_enable) 211 mfspr r3, HID0 212 li r5, HID0_DCFI|HID0_DLOCK 213 andc r3, r3, r5 214 mtspr HID0, r3 /* no invalidate, unlock */ 215 ori r3, r3, HID0_DCE 216 ori r5, r3, HID0_DCFI 217 mtspr HID0, r5 /* enable + invalidate */ 218 mtspr HID0, r3 /* enable */ 219 sync 220 blr 221 222/* 223 * Enable data cache(s) - L1 and optionally L2 224 * Calls l2cache_enable. LR saved in r5 225 */ 226_GLOBAL(dcache_enable) 227 mfspr r3, HID0 228 li r5, HID0_DCFI|HID0_DLOCK 229 andc r3, r3, r5 230 mtspr HID0, r3 /* no invalidate, unlock */ 231 ori r3, r3, HID0_DCE 232 ori r5, r3, HID0_DCFI 233 mtspr HID0, r5 /* enable + invalidate */ 234 mtspr HID0, r3 /* enable */ 235 sync 236#ifdef CONFIG_SYS_L2 237 mflr r5 238 bl l2cache_enable /* uses r3 and r4 */ 239 sync 240 mtlr r5 241#endif 242 blr 243 244 245/* 246 * Disable data cache(s) - L1 and optionally L2 247 * Calls flush_dcache and l2cache_disable_no_flush. 248 * LR saved in r4 249 */ 250_GLOBAL(dcache_disable) 251 mflr r4 /* save link register */ 252 bl flush_dcache /* uses r3 and r5 */ 253 sync 254 mfspr r3, HID0 255 li r5, HID0_DCFI|HID0_DLOCK 256 andc r3, r3, r5 257 mtspr HID0, r3 /* no invalidate, unlock */ 258 li r5, HID0_DCE|HID0_DCFI 259 andc r3, r3, r5 /* no enable, no invalidate */ 260 mtspr HID0, r3 261 sync 262#ifdef CONFIG_SYS_L2 263 bl l2cache_disable_no_flush /* uses r3 */ 264#endif 265 mtlr r4 /* restore link register */ 266 blr 267 268/* 269 * Is data cache enabled? 270 */ 271_GLOBAL(dcache_status) 272 mfspr r3, HID0 273 andi. r3, r3, HID0_DCE 274 blr 275 276/* 277 * Invalidate L2 cache using L2I, assume L2 is enabled 278 */ 279_GLOBAL(l2cache_invalidate) 280 mfspr r3, l2cr 281 rlwinm. r3, r3, 0, 0, 0 282 beq 1f 283 284 mfspr r3, l2cr 285 rlwinm r3, r3, 0, 1, 31 286 287#ifdef CONFIG_ALTIVEC 288 dssall 289#endif 290 sync 291 mtspr l2cr, r3 292 sync 2931: mfspr r3, l2cr 294 oris r3, r3, L2CR_L2I@h 295 mtspr l2cr, r3 296 297invl2: 298 mfspr r3, l2cr 299 andis. r3, r3, L2CR_L2I@h 300 bne invl2 301 blr 302 303/* 304 * Enable L2 cache 305 * Calls l2cache_invalidate. LR is saved in r4 306 */ 307_GLOBAL(l2cache_enable) 308 mflr r4 /* save link register */ 309 bl l2cache_invalidate /* uses r3 */ 310 sync 311 lis r3, L2_ENABLE@h 312 ori r3, r3, L2_ENABLE@l 313 mtspr l2cr, r3 314 isync 315 mtlr r4 /* restore link register */ 316 blr 317 318/* 319 * Disable L2 cache 320 * Calls flush_dcache. LR is saved in r4 321 */ 322_GLOBAL(l2cache_disable) 323 mflr r4 /* save link register */ 324 bl flush_dcache /* uses r3 and r5 */ 325 sync 326 mtlr r4 /* restore link register */ 327l2cache_disable_no_flush: /* provide way to disable L2 w/o flushing */ 328 lis r3, L2_INIT@h 329 ori r3, r3, L2_INIT@l 330 mtspr l2cr, r3 331 isync 332 blr 333