Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-btrfs-devel.git] / arch / mn10300 / mm / cache-inv-by-tag.S
blobccedce9c144d30459b8d092959247d4713ee03f0
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"
20 #define mn10300_local_dcache_inv_range_intr_interval \
21         +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
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
27         .am33_2
29         .globl  mn10300_local_icache_inv_page
30         .globl  mn10300_local_icache_inv_range
31         .globl  mn10300_local_icache_inv_range2
33 mn10300_local_icache_inv_page   = mn10300_local_icache_inv
34 mn10300_local_icache_inv_range  = mn10300_local_icache_inv
35 mn10300_local_icache_inv_range2 = mn10300_local_icache_inv
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
47 mn10300_icache_inv              = mn10300_local_icache_inv
48 mn10300_icache_inv_page         = mn10300_local_icache_inv_page
49 mn10300_icache_inv_range        = mn10300_local_icache_inv_range
50 mn10300_icache_inv_range2       = mn10300_local_icache_inv_range2
51 mn10300_dcache_inv              = mn10300_local_dcache_inv
52 mn10300_dcache_inv_page         = mn10300_local_dcache_inv_page
53 mn10300_dcache_inv_range        = mn10300_local_dcache_inv_range
54 mn10300_dcache_inv_range2       = mn10300_local_dcache_inv_range2
56 #endif /* !CONFIG_SMP */
58 ###############################################################################
60 # void mn10300_local_icache_inv(void)
61 # Invalidate the entire icache
63 ###############################################################################
64         ALIGN
65         .globl  mn10300_local_icache_inv
66         .type   mn10300_local_icache_inv,@function
67 mn10300_local_icache_inv:
68         mov     CHCTR,a0
70         movhu   (a0),d0
71         btst    CHCTR_ICEN,d0
72         beq     mn10300_local_icache_inv_end
74         invalidate_icache 1
76 mn10300_local_icache_inv_end:
77         ret     [],0
78         .size   mn10300_local_icache_inv,.-mn10300_local_icache_inv
80 ###############################################################################
82 # void mn10300_local_dcache_inv(void)
83 # Invalidate the entire dcache
85 ###############################################################################
86         ALIGN
87         .globl  mn10300_local_dcache_inv
88         .type   mn10300_local_dcache_inv,@function
89 mn10300_local_dcache_inv:
90         mov     CHCTR,a0
92         movhu   (a0),d0
93         btst    CHCTR_DCEN,d0
94         beq     mn10300_local_dcache_inv_end
96         invalidate_dcache 1
98 mn10300_local_dcache_inv_end:
99         ret     [],0
100         .size   mn10300_local_dcache_inv,.-mn10300_local_dcache_inv
102 ###############################################################################
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
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
117 mn10300_local_dcache_inv_page:
118         and     ~(PAGE_SIZE-1),d0
119         mov     PAGE_SIZE,d1
120 mn10300_local_dcache_inv_range2:
121         add     d0,d1
122 mn10300_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
132         bra     mn10300_local_dcache_flush_inv_range
134 #endif /* CONFIG_MN10300_CACHE_WBACK */
136         movm    [d2,d3,a2],(sp)
138         mov     CHCTR,a2
139         movhu   (a2),d2
140         btst    CHCTR_DCEN,d2
141         beq     mn10300_local_dcache_inv_range_end
143 #ifndef CONFIG_MN10300_CACHE_WBACK
144         and     L1_CACHE_TAG_MASK,d0            # round start addr down
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
151         clr     d2                              # we're going to clear tag RAM
152                                                 # entries
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
162         sub     a1,d1
163         lsr     L1_CACHE_SHIFT,d1               # total number of entries to
164                                                 # examine
166         and     ~(L1_CACHE_DISPARITY-1),a1      # determine comparator base
168 mn10300_local_dcache_inv_range_outer_loop:
169         LOCAL_CLI_SAVE(d3)
171         # disable the dcache
172         movhu   (a2),d0
173         and     ~CHCTR_DCEN,d0
174         movhu   d0,(a2)
176         # and wait for it to calm down
177         setlb
178         movhu   (a2),d0
179         btst    CHCTR_DCBUSY,d0
180         lne
182 mn10300_local_dcache_inv_range_loop:
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
190         xor     a1,d0
191         lsr     12,d0
192         bne     mn10300_local_dcache_inv_range_skip_0   # jump if not this cacheline
194         mov     d2,(L1_CACHE_WAYDISP*0,a0)      # kill the tag
196 mn10300_local_dcache_inv_range_skip_0:
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
204         xor     a1,d0
205         lsr     12,d0
206         bne     mn10300_local_dcache_inv_range_skip_1   # jump if not this cacheline
208         mov     d2,(L1_CACHE_WAYDISP*1,a0)      # kill the tag
210 mn10300_local_dcache_inv_range_skip_1:
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
218         xor     a1,d0
219         lsr     12,d0
220         bne     mn10300_local_dcache_inv_range_skip_2   # jump if not this cacheline
222         mov     d2,(L1_CACHE_WAYDISP*2,a0)      # kill the tag
224 mn10300_local_dcache_inv_range_skip_2:
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
232         xor     a1,d0
233         lsr     12,d0
234         bne     mn10300_local_dcache_inv_range_skip_3   # jump if not this cacheline
236         mov     d2,(L1_CACHE_WAYDISP*3,a0)      # kill the tag
238 mn10300_local_dcache_inv_range_skip_3:
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
251         # wait for the cache to finish what it's doing
252         setlb
253         movhu   (a2),d0
254         btst    CHCTR_DCBUSY,d0
255         lne
257         # and reenable it
258         or      CHCTR_DCEN,d0
259         movhu   d0,(a2)
260         movhu   (a2),d0
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)
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
272 mn10300_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