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