linux/arch/mn10300/mm/cache-inv-by-tag.S
<<
>>
Prefs
   1/* MN10300 CPU core caching routines
   2 *
   3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Howells (dhowells@redhat.com)
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public Licence
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the Licence, or (at your option) any later version.
  10 */
  11#include <linux/sys.h>
  12#include <linux/linkage.h>
  13#include <asm/smp.h>
  14#include <asm/page.h>
  15#include <asm/cache.h>
  16#include <asm/irqflags.h>
  17#include <asm/cacheflush.h>
  18#include "cache.inc"
  19
  20#define mn10300_local_dcache_inv_range_intr_interval \
  21        +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
  22
  23#if mn10300_local_dcache_inv_range_intr_interval > 0xff
  24#error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less
  25#endif
  26
  27        .am33_2
  28
  29        .globl  mn10300_local_icache_inv_page
  30        .globl  mn10300_local_icache_inv_range
  31        .globl  mn10300_local_icache_inv_range2
  32
  33mn10300_local_icache_inv_page   = mn10300_local_icache_inv
  34mn10300_local_icache_inv_range  = mn10300_local_icache_inv
  35mn10300_local_icache_inv_range2 = mn10300_local_icache_inv
  36
  37#ifndef CONFIG_SMP
  38        .globl  mn10300_icache_inv
  39        .globl  mn10300_icache_inv_page
  40        .globl  mn10300_icache_inv_range
  41        .globl  mn10300_icache_inv_range2
  42        .globl  mn10300_dcache_inv
  43        .globl  mn10300_dcache_inv_page
  44        .globl  mn10300_dcache_inv_range
  45        .globl  mn10300_dcache_inv_range2
  46
  47mn10300_icache_inv              = mn10300_local_icache_inv
  48mn10300_icache_inv_page         = mn10300_local_icache_inv_page
  49mn10300_icache_inv_range        = mn10300_local_icache_inv_range
  50mn10300_icache_inv_range2       = mn10300_local_icache_inv_range2
  51mn10300_dcache_inv              = mn10300_local_dcache_inv
  52mn10300_dcache_inv_page         = mn10300_local_dcache_inv_page
  53mn10300_dcache_inv_range        = mn10300_local_dcache_inv_range
  54mn10300_dcache_inv_range2       = mn10300_local_dcache_inv_range2
  55
  56#endif /* !CONFIG_SMP */
  57
  58###############################################################################
  59#
  60# void mn10300_local_icache_inv(void)
  61# Invalidate the entire icache
  62#
  63###############################################################################
  64        ALIGN
  65        .globl  mn10300_local_icache_inv
  66        .type   mn10300_local_icache_inv,@function
  67mn10300_local_icache_inv:
  68        mov     CHCTR,a0
  69
  70        movhu   (a0),d0
  71        btst    CHCTR_ICEN,d0
  72        beq     mn10300_local_icache_inv_end
  73
  74        invalidate_icache 1
  75
  76mn10300_local_icache_inv_end:
  77        ret     [],0
  78        .size   mn10300_local_icache_inv,.-mn10300_local_icache_inv
  79
  80###############################################################################
  81#
  82# void mn10300_local_dcache_inv(void)
  83# Invalidate the entire dcache
  84#
  85###############################################################################
  86        ALIGN
  87        .globl  mn10300_local_dcache_inv
  88        .type   mn10300_local_dcache_inv,@function
  89mn10300_local_dcache_inv:
  90        mov     CHCTR,a0
  91
  92        movhu   (a0),d0
  93        btst    CHCTR_DCEN,d0
  94        beq     mn10300_local_dcache_inv_end
  95
  96        invalidate_dcache 1
  97
  98mn10300_local_dcache_inv_end:
  99        ret     [],0
 100        .size   mn10300_local_dcache_inv,.-mn10300_local_dcache_inv
 101
 102###############################################################################
 103#
 104# void mn10300_local_dcache_inv_range(unsigned long start, unsigned long end)
 105# void mn10300_local_dcache_inv_range2(unsigned long start, unsigned long size)
 106# void mn10300_local_dcache_inv_page(unsigned long start)
 107# Invalidate a range of addresses on a page in the dcache
 108#
 109###############################################################################
 110        ALIGN
 111        .globl  mn10300_local_dcache_inv_page
 112        .globl  mn10300_local_dcache_inv_range
 113        .globl  mn10300_local_dcache_inv_range2
 114        .type   mn10300_local_dcache_inv_page,@function
 115        .type   mn10300_local_dcache_inv_range,@function
 116        .type   mn10300_local_dcache_inv_range2,@function
 117mn10300_local_dcache_inv_page:
 118        and     ~(PAGE_SIZE-1),d0
 119        mov     PAGE_SIZE,d1
 120mn10300_local_dcache_inv_range2:
 121        add     d0,d1
 122mn10300_local_dcache_inv_range:
 123        # If we are in writeback mode we check the start and end alignments,
 124        # and if they're not cacheline-aligned, we must flush any bits outside
 125        # the range that share cachelines with stuff inside the range
 126#ifdef CONFIG_MN10300_CACHE_WBACK
 127        btst    ~L1_CACHE_TAG_MASK,d0
 128        bne     1f
 129        btst    ~L1_CACHE_TAG_MASK,d1
 130        beq     2f
 1311:
 132        bra     mn10300_local_dcache_flush_inv_range
 1332:
 134#endif /* CONFIG_MN10300_CACHE_WBACK */
 135
 136        movm    [d2,d3,a2],(sp)
 137
 138        mov     CHCTR,a2
 139        movhu   (a2),d2
 140        btst    CHCTR_DCEN,d2
 141        beq     mn10300_local_dcache_inv_range_end
 142
 143#ifndef CONFIG_MN10300_CACHE_WBACK
 144        and     L1_CACHE_TAG_MASK,d0            # round start addr down
 145
 146        add     L1_CACHE_BYTES,d1               # round end addr up
 147        and     L1_CACHE_TAG_MASK,d1
 148#endif /* !CONFIG_MN10300_CACHE_WBACK */
 149        mov     d0,a1
 150
 151        clr     d2                              # we're going to clear tag RAM
 152                                                # entries
 153
 154        # read the tags from the tag RAM, and if they indicate a valid dirty
 155        # cache line then invalidate that line
 156        mov     DCACHE_TAG(0,0),a0
 157        mov     a1,d0
 158        and     L1_CACHE_TAG_ENTRY,d0
 159        add     d0,a0                           # starting dcache tag RAM
 160                                                # access address
 161
 162        sub     a1,d1
 163        lsr     L1_CACHE_SHIFT,d1               # total number of entries to
 164                                                # examine
 165
 166        and     ~(L1_CACHE_DISPARITY-1),a1      # determine comparator base
 167
 168mn10300_local_dcache_inv_range_outer_loop:
 169        LOCAL_CLI_SAVE(d3)
 170
 171        # disable the dcache
 172        movhu   (a2),d0
 173        and     ~CHCTR_DCEN,d0
 174        movhu   d0,(a2)
 175
 176        # and wait for it to calm down
 177        setlb
 178        movhu   (a2),d0
 179        btst    CHCTR_DCBUSY,d0
 180        lne
 181
 182mn10300_local_dcache_inv_range_loop:
 183
 184        # process the way 0 slot
 185        mov     (L1_CACHE_WAYDISP*0,a0),d0      # read the tag in the way 0 slot
 186        btst    L1_CACHE_TAG_VALID,d0
 187        beq     mn10300_local_dcache_inv_range_skip_0   # jump if this cacheline
 188                                                # is not valid
 189
 190        xor     a1,d0
 191        lsr     12,d0
 192        bne     mn10300_local_dcache_inv_range_skip_0   # jump if not this cacheline
 193
 194        mov     d2,(L1_CACHE_WAYDISP*0,a0)      # kill the tag
 195
 196mn10300_local_dcache_inv_range_skip_0:
 197
 198        # process the way 1 slot
 199        mov     (L1_CACHE_WAYDISP*1,a0),d0      # read the tag in the way 1 slot
 200        btst    L1_CACHE_TAG_VALID,d0
 201        beq     mn10300_local_dcache_inv_range_skip_1   # jump if this cacheline
 202                                                # is not valid
 203
 204        xor     a1,d0
 205        lsr     12,d0
 206        bne     mn10300_local_dcache_inv_range_skip_1   # jump if not this cacheline
 207
 208        mov     d2,(L1_CACHE_WAYDISP*1,a0)      # kill the tag
 209
 210mn10300_local_dcache_inv_range_skip_1:
 211
 212        # process the way 2 slot
 213        mov     (L1_CACHE_WAYDISP*2,a0),d0      # read the tag in the way 2 slot
 214        btst    L1_CACHE_TAG_VALID,d0
 215        beq     mn10300_local_dcache_inv_range_skip_2   # jump if this cacheline
 216                                                # is not valid
 217
 218        xor     a1,d0
 219        lsr     12,d0
 220        bne     mn10300_local_dcache_inv_range_skip_2   # jump if not this cacheline
 221
 222        mov     d2,(L1_CACHE_WAYDISP*2,a0)      # kill the tag
 223
 224mn10300_local_dcache_inv_range_skip_2:
 225
 226        # process the way 3 slot
 227        mov     (L1_CACHE_WAYDISP*3,a0),d0      # read the tag in the way 3 slot
 228        btst    L1_CACHE_TAG_VALID,d0
 229        beq     mn10300_local_dcache_inv_range_skip_3   # jump if this cacheline
 230                                                # is not valid
 231
 232        xor     a1,d0
 233        lsr     12,d0
 234        bne     mn10300_local_dcache_inv_range_skip_3   # jump if not this cacheline
 235
 236        mov     d2,(L1_CACHE_WAYDISP*3,a0)      # kill the tag
 237
 238mn10300_local_dcache_inv_range_skip_3:
 239
 240        # approx every N steps we re-enable the cache and see if there are any
 241        # interrupts to be processed
 242        # we also break out if we've reached the end of the loop
 243        # (the bottom nibble of the count is zero in both cases)
 244        add     L1_CACHE_BYTES,a0
 245        add     L1_CACHE_BYTES,a1
 246        and     ~L1_CACHE_WAYDISP,a0
 247        add     -1,d1
 248        btst    mn10300_local_dcache_inv_range_intr_interval,d1
 249        bne     mn10300_local_dcache_inv_range_loop
 250
 251        # wait for the cache to finish what it's doing
 252        setlb
 253        movhu   (a2),d0
 254        btst    CHCTR_DCBUSY,d0
 255        lne
 256
 257        # and reenable it
 258        or      CHCTR_DCEN,d0
 259        movhu   d0,(a2)
 260        movhu   (a2),d0
 261
 262        # re-enable interrupts
 263        # - we don't bother with delay NOPs as we'll have enough instructions
 264        #   before we disable interrupts again to give the interrupts a chance
 265        #   to happen
 266        LOCAL_IRQ_RESTORE(d3)
 267
 268        # go around again if the counter hasn't yet reached zero
 269        add     0,d1
 270        bne     mn10300_local_dcache_inv_range_outer_loop
 271
 272mn10300_local_dcache_inv_range_end:
 273        ret     [d2,d3,a2],12
 274        .size   mn10300_local_dcache_inv_page,.-mn10300_local_dcache_inv_page
 275        .size   mn10300_local_dcache_inv_range,.-mn10300_local_dcache_inv_range
 276        .size   mn10300_local_dcache_inv_range2,.-mn10300_local_dcache_inv_range2
 277