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