uboot/arch/powerpc/cpu/mpc86xx/cache.S
<<
>>
Prefs
   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