uboot/arch/powerpc/cpu/mpc86xx/cache.S
<<
>>
Prefs
   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 * Flush a particular page from the data cache to RAM.
 119 * Note: this is necessary because the instruction cache does *not*
 120 * snoop from the data cache.
 121 *
 122 *      void __flush_page_to_ram(void *page)
 123 */
 124_GLOBAL(__flush_page_to_ram)
 125        rlwinm  r3,r3,0,0,19            /* Get page base address */
 126        li      r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
 127        mtctr   r4
 128        mr      r6,r3
 1290:      dcbst   0,r3                    /* Write line to ram */
 130        addi    r3,r3,CACHE_LINE_SIZE
 131        bdnz    0b
 132        sync
 133        mtctr   r4
 1341:      icbi    0,r6
 135        addi    r6,r6,CACHE_LINE_SIZE
 136        bdnz    1b
 137        sync
 138        isync
 139        blr
 140
 141/*
 142 * Flush a particular page from the instruction cache.
 143 * Note: this is necessary because the instruction cache does *not*
 144 * snoop from the data cache.
 145 *
 146 *      void __flush_icache_page(void *page)
 147 */
 148_GLOBAL(__flush_icache_page)
 149        li      r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
 150        mtctr   r4
 1511:      icbi    0,r3
 152        addi    r3,r3,CACHE_LINE_SIZE
 153        bdnz    1b
 154        sync
 155        isync
 156        blr
 157
 158/*
 159 * Clear a page using the dcbz instruction, which doesn't cause any
 160 * memory traffic (except to write out any cache lines which get
 161 * displaced).  This only works on cacheable memory.
 162 */
 163_GLOBAL(clear_page)
 164        li      r0,4096/CACHE_LINE_SIZE
 165        mtctr   r0
 1661:      dcbz    0,r3
 167        addi    r3,r3,CACHE_LINE_SIZE
 168        bdnz    1b
 169        blr
 170
 171/*
 172 * Enable L1 Instruction cache
 173 */
 174_GLOBAL(icache_enable)
 175        mfspr   r3, HID0
 176        li      r5, HID0_ICFI|HID0_ILOCK
 177        andc    r3, r3, r5
 178        ori     r3, r3, HID0_ICE
 179        ori     r5, r3, HID0_ICFI
 180        mtspr   HID0, r5
 181        mtspr   HID0, r3
 182        isync
 183        blr
 184
 185/*
 186 * Disable L1 Instruction cache
 187 */
 188_GLOBAL(icache_disable)
 189        mflr    r4
 190        bl      invalidate_l1_instruction_cache         /* uses r3 */
 191        sync
 192        mtlr    r4
 193        mfspr   r3, HID0
 194        li      r5, 0
 195        ori     r5, r5, HID0_ICE
 196        andc    r3, r3, r5
 197        mtspr   HID0, r3
 198        isync
 199        blr
 200
 201/*
 202 * Is instruction cache enabled?
 203 */
 204_GLOBAL(icache_status)
 205        mfspr   r3, HID0
 206        andi.   r3, r3, HID0_ICE
 207        blr
 208
 209
 210_GLOBAL(l1dcache_enable)
 211        mfspr   r3, HID0
 212        li      r5, HID0_DCFI|HID0_DLOCK
 213        andc    r3, r3, r5
 214        mtspr   HID0, r3                /* no invalidate, unlock */
 215        ori     r3, r3, HID0_DCE
 216        ori     r5, r3, HID0_DCFI
 217        mtspr   HID0, r5                /* enable + invalidate */
 218        mtspr   HID0, r3                /* enable */
 219        sync
 220        blr
 221
 222/*
 223 * Enable data cache(s) - L1 and optionally L2
 224 * Calls l2cache_enable. LR saved in r5
 225 */
 226_GLOBAL(dcache_enable)
 227        mfspr   r3, HID0
 228        li      r5, HID0_DCFI|HID0_DLOCK
 229        andc    r3, r3, r5
 230        mtspr   HID0, r3                /* no invalidate, unlock */
 231        ori     r3, r3, HID0_DCE
 232        ori     r5, r3, HID0_DCFI
 233        mtspr   HID0, r5                /* enable + invalidate */
 234        mtspr   HID0, r3                /* enable */
 235        sync
 236#ifdef CONFIG_SYS_L2
 237        mflr    r5
 238        bl      l2cache_enable          /* uses r3 and r4 */
 239        sync
 240        mtlr    r5
 241#endif
 242        blr
 243
 244
 245/*
 246 * Disable data cache(s) - L1 and optionally L2
 247 * Calls flush_dcache and l2cache_disable_no_flush.
 248 * LR saved in r4
 249 */
 250_GLOBAL(dcache_disable)
 251        mflr    r4                      /* save link register */
 252        bl      flush_dcache    /* uses r3 and r5 */
 253        sync
 254        mfspr   r3, HID0
 255        li      r5, HID0_DCFI|HID0_DLOCK
 256        andc    r3, r3, r5
 257        mtspr   HID0, r3                /* no invalidate, unlock */
 258        li      r5, HID0_DCE|HID0_DCFI
 259        andc    r3, r3, r5              /* no enable, no invalidate */
 260        mtspr   HID0, r3
 261        sync
 262#ifdef CONFIG_SYS_L2
 263        bl      l2cache_disable_no_flush /* uses r3 */
 264#endif
 265        mtlr    r4                      /* restore link register */
 266        blr
 267
 268/*
 269 * Is data cache enabled?
 270 */
 271_GLOBAL(dcache_status)
 272        mfspr   r3, HID0
 273        andi.   r3, r3, HID0_DCE
 274        blr
 275
 276/*
 277 * Invalidate L2 cache using L2I, assume L2 is enabled
 278 */
 279_GLOBAL(l2cache_invalidate)
 280        mfspr   r3, l2cr
 281        rlwinm. r3, r3, 0, 0, 0
 282        beq     1f
 283
 284        mfspr   r3, l2cr
 285        rlwinm  r3, r3, 0, 1, 31
 286
 287#ifdef  CONFIG_ALTIVEC
 288        dssall
 289#endif
 290        sync
 291        mtspr   l2cr, r3
 292        sync
 2931:      mfspr   r3, l2cr
 294        oris    r3, r3, L2CR_L2I@h
 295        mtspr   l2cr, r3
 296
 297invl2:
 298        mfspr   r3, l2cr
 299        andis.  r3, r3, L2CR_L2I@h
 300        bne     invl2
 301        blr
 302
 303/*
 304 * Enable L2 cache
 305 * Calls l2cache_invalidate. LR is saved in r4
 306 */
 307_GLOBAL(l2cache_enable)
 308        mflr    r4                      /* save link register */
 309        bl      l2cache_invalidate      /* uses r3 */
 310        sync
 311        lis     r3, L2_ENABLE@h
 312        ori     r3, r3, L2_ENABLE@l
 313        mtspr   l2cr, r3
 314        isync
 315        mtlr    r4                      /* restore link register */
 316        blr
 317
 318/*
 319 * Disable L2 cache
 320 * Calls flush_dcache. LR is saved in r4
 321 */
 322_GLOBAL(l2cache_disable)
 323        mflr    r4                      /* save link register */
 324        bl      flush_dcache            /* uses r3 and r5 */
 325        sync
 326        mtlr    r4                      /* restore link register */
 327l2cache_disable_no_flush:               /* provide way to disable L2 w/o flushing */
 328        lis     r3, L2_INIT@h
 329        ori     r3, r3, L2_INIT@l
 330        mtspr   l2cr, r3
 331        isync
 332        blr
 333