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 * Write any modified data cache blocks out to memory 119 * and invalidate the corresponding instruction cache blocks. 120 * 121 * flush_dcache_range(unsigned long start, unsigned long stop) 122 */ 123_GLOBAL(flush_dcache_range) 124 li r5,CACHE_LINE_SIZE-1 125 andc r3,r3,r5 126 subf r4,r3,r4 127 add r4,r4,r5 128 srwi. r4,r4,LG_CACHE_LINE_SIZE 129 beqlr 130 mtctr r4 131 132 sync 1331: dcbf 0,r3 134 addi r3,r3,CACHE_LINE_SIZE 135 bdnz 1b 136 sync /* wait for dcbf's to get to ram */ 137 blr 138 139/* 140 * Like above, but invalidate the D-cache. This is used by the 8xx 141 * to invalidate the cache so the PPC core doesn't get stale data 142 * from the CPM (no cache snooping here :-). 143 * 144 * invalidate_dcache_range(unsigned long start, unsigned long stop) 145 */ 146_GLOBAL(invalidate_dcache_range) 147 li r5,CACHE_LINE_SIZE-1 148 andc r3,r3,r5 149 subf r4,r3,r4 150 add r4,r4,r5 151 srwi. r4,r4,LG_CACHE_LINE_SIZE 152 beqlr 153 mtctr r4 154 155 sync 1561: dcbi 0,r3 157 addi r3,r3,CACHE_LINE_SIZE 158 bdnz 1b 159 sync /* wait for dcbi's to get to ram */ 160 blr 161 162/* 163 * Flush a particular page from the data cache to RAM. 164 * Note: this is necessary because the instruction cache does *not* 165 * snoop from the data cache. 166 * 167 * void __flush_page_to_ram(void *page) 168 */ 169_GLOBAL(__flush_page_to_ram) 170 rlwinm r3,r3,0,0,19 /* Get page base address */ 171 li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */ 172 mtctr r4 173 mr r6,r3 1740: dcbst 0,r3 /* Write line to ram */ 175 addi r3,r3,CACHE_LINE_SIZE 176 bdnz 0b 177 sync 178 mtctr r4 1791: icbi 0,r6 180 addi r6,r6,CACHE_LINE_SIZE 181 bdnz 1b 182 sync 183 isync 184 blr 185 186/* 187 * Flush a particular page from the instruction cache. 188 * Note: this is necessary because the instruction cache does *not* 189 * snoop from the data cache. 190 * 191 * void __flush_icache_page(void *page) 192 */ 193_GLOBAL(__flush_icache_page) 194 li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */ 195 mtctr r4 1961: icbi 0,r3 197 addi r3,r3,CACHE_LINE_SIZE 198 bdnz 1b 199 sync 200 isync 201 blr 202 203/* 204 * Clear a page using the dcbz instruction, which doesn't cause any 205 * memory traffic (except to write out any cache lines which get 206 * displaced). This only works on cacheable memory. 207 */ 208_GLOBAL(clear_page) 209 li r0,4096/CACHE_LINE_SIZE 210 mtctr r0 2111: dcbz 0,r3 212 addi r3,r3,CACHE_LINE_SIZE 213 bdnz 1b 214 blr 215 216/* 217 * Enable L1 Instruction cache 218 */ 219_GLOBAL(icache_enable) 220 mfspr r3, HID0 221 li r5, HID0_ICFI|HID0_ILOCK 222 andc r3, r3, r5 223 ori r3, r3, HID0_ICE 224 ori r5, r3, HID0_ICFI 225 mtspr HID0, r5 226 mtspr HID0, r3 227 isync 228 blr 229 230/* 231 * Disable L1 Instruction cache 232 */ 233_GLOBAL(icache_disable) 234 mflr r4 235 bl invalidate_l1_instruction_cache /* uses r3 */ 236 sync 237 mtlr r4 238 mfspr r3, HID0 239 li r5, 0 240 ori r5, r5, HID0_ICE 241 andc r3, r3, r5 242 mtspr HID0, r3 243 isync 244 blr 245 246/* 247 * Is instruction cache enabled? 248 */ 249_GLOBAL(icache_status) 250 mfspr r3, HID0 251 andi. r3, r3, HID0_ICE 252 blr 253 254 255_GLOBAL(l1dcache_enable) 256 mfspr r3, HID0 257 li r5, HID0_DCFI|HID0_DLOCK 258 andc r3, r3, r5 259 mtspr HID0, r3 /* no invalidate, unlock */ 260 ori r3, r3, HID0_DCE 261 ori r5, r3, HID0_DCFI 262 mtspr HID0, r5 /* enable + invalidate */ 263 mtspr HID0, r3 /* enable */ 264 sync 265 blr 266 267/* 268 * Enable data cache(s) - L1 and optionally L2 269 * Calls l2cache_enable. LR saved in r5 270 */ 271_GLOBAL(dcache_enable) 272 mfspr r3, HID0 273 li r5, HID0_DCFI|HID0_DLOCK 274 andc r3, r3, r5 275 mtspr HID0, r3 /* no invalidate, unlock */ 276 ori r3, r3, HID0_DCE 277 ori r5, r3, HID0_DCFI 278 mtspr HID0, r5 /* enable + invalidate */ 279 mtspr HID0, r3 /* enable */ 280 sync 281#ifdef CONFIG_SYS_L2 282 mflr r5 283 bl l2cache_enable /* uses r3 and r4 */ 284 sync 285 mtlr r5 286#endif 287 blr 288 289 290/* 291 * Disable data cache(s) - L1 and optionally L2 292 * Calls flush_dcache and l2cache_disable_no_flush. 293 * LR saved in r4 294 */ 295_GLOBAL(dcache_disable) 296 mflr r4 /* save link register */ 297 bl flush_dcache /* uses r3 and r5 */ 298 sync 299 mfspr r3, HID0 300 li r5, HID0_DCFI|HID0_DLOCK 301 andc r3, r3, r5 302 mtspr HID0, r3 /* no invalidate, unlock */ 303 li r5, HID0_DCE|HID0_DCFI 304 andc r3, r3, r5 /* no enable, no invalidate */ 305 mtspr HID0, r3 306 sync 307#ifdef CONFIG_SYS_L2 308 bl l2cache_disable_no_flush /* uses r3 */ 309#endif 310 mtlr r4 /* restore link register */ 311 blr 312 313/* 314 * Is data cache enabled? 315 */ 316_GLOBAL(dcache_status) 317 mfspr r3, HID0 318 andi. r3, r3, HID0_DCE 319 blr 320 321/* 322 * Invalidate L2 cache using L2I, assume L2 is enabled 323 */ 324_GLOBAL(l2cache_invalidate) 325 mfspr r3, l2cr 326 rlwinm. r3, r3, 0, 0, 0 327 beq 1f 328 329 mfspr r3, l2cr 330 rlwinm r3, r3, 0, 1, 31 331 332#ifdef CONFIG_ALTIVEC 333 dssall 334#endif 335 sync 336 mtspr l2cr, r3 337 sync 3381: mfspr r3, l2cr 339 oris r3, r3, L2CR_L2I@h 340 mtspr l2cr, r3 341 342invl2: 343 mfspr r3, l2cr 344 andis. r3, r3, L2CR_L2I@h 345 bne invl2 346 blr 347 348/* 349 * Enable L2 cache 350 * Calls l2cache_invalidate. LR is saved in r4 351 */ 352_GLOBAL(l2cache_enable) 353 mflr r4 /* save link register */ 354 bl l2cache_invalidate /* uses r3 */ 355 sync 356 lis r3, L2_ENABLE@h 357 ori r3, r3, L2_ENABLE@l 358 mtspr l2cr, r3 359 isync 360 mtlr r4 /* restore link register */ 361 blr 362 363/* 364 * Disable L2 cache 365 * Calls flush_dcache. LR is saved in r4 366 */ 367_GLOBAL(l2cache_disable) 368 mflr r4 /* save link register */ 369 bl flush_dcache /* uses r3 and r5 */ 370 sync 371 mtlr r4 /* restore link register */ 372l2cache_disable_no_flush: /* provide way to disable L2 w/o flushing */ 373 lis r3, L2_INIT@h 374 ori r3, r3, L2_INIT@l 375 mtspr l2cr, r3 376 isync 377 blr 378