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