Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / mn10300 / mm / cache-inv-by-tag.S
blobe9713b40c0ff4823ead75d4e81b09a71138e9531
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>
19 #define mn10300_local_dcache_inv_range_intr_interval \
20         +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
22 #if mn10300_local_dcache_inv_range_intr_interval > 0xff
23 #error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less
24 #endif
26         .am33_2
28         .globl  mn10300_local_icache_inv_page
29         .globl  mn10300_local_icache_inv_range
30         .globl  mn10300_local_icache_inv_range2
32 mn10300_local_icache_inv_page   = mn10300_local_icache_inv
33 mn10300_local_icache_inv_range  = mn10300_local_icache_inv
34 mn10300_local_icache_inv_range2 = mn10300_local_icache_inv
36 #ifndef CONFIG_SMP
37         .globl  mn10300_icache_inv
38         .globl  mn10300_icache_inv_page
39         .globl  mn10300_icache_inv_range
40         .globl  mn10300_icache_inv_range2
41         .globl  mn10300_dcache_inv
42         .globl  mn10300_dcache_inv_page
43         .globl  mn10300_dcache_inv_range
44         .globl  mn10300_dcache_inv_range2
46 mn10300_icache_inv              = mn10300_local_icache_inv
47 mn10300_icache_inv_page         = mn10300_local_icache_inv_page
48 mn10300_icache_inv_range        = mn10300_local_icache_inv_range
49 mn10300_icache_inv_range2       = mn10300_local_icache_inv_range2
50 mn10300_dcache_inv              = mn10300_local_dcache_inv
51 mn10300_dcache_inv_page         = mn10300_local_dcache_inv_page
52 mn10300_dcache_inv_range        = mn10300_local_dcache_inv_range
53 mn10300_dcache_inv_range2       = mn10300_local_dcache_inv_range2
55 #endif /* !CONFIG_SMP */
57 ###############################################################################
59 # void mn10300_local_icache_inv(void)
60 # Invalidate the entire icache
62 ###############################################################################
63         ALIGN
64         .globl  mn10300_local_icache_inv
65         .type   mn10300_local_icache_inv,@function
66 mn10300_local_icache_inv:
67         mov     CHCTR,a0
69         movhu   (a0),d0
70         btst    CHCTR_ICEN,d0
71         beq     mn10300_local_icache_inv_end
73 #if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
74         LOCAL_CLI_SAVE(d1)
76         # disable the icache
77         and     ~CHCTR_ICEN,d0
78         movhu   d0,(a0)
80         # and wait for it to calm down
81         setlb
82         movhu   (a0),d0
83         btst    CHCTR_ICBUSY,d0
84         lne
86         # invalidate
87         or      CHCTR_ICINV,d0
88         movhu   d0,(a0)
90         # wait for the cache to finish
91         mov     CHCTR,a0
92         setlb
93         movhu   (a0),d0
94         btst    CHCTR_ICBUSY,d0
95         lne
97         # and reenable it
98         and     ~CHCTR_ICINV,d0
99         or      CHCTR_ICEN,d0
100         movhu   d0,(a0)
101         movhu   (a0),d0
103         LOCAL_IRQ_RESTORE(d1)
104 #else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
105         # invalidate
106         or      CHCTR_ICINV,d0
107         movhu   d0,(a0)
108         movhu   (a0),d0
109 #endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
111 mn10300_local_icache_inv_end:
112         ret     [],0
113         .size   mn10300_local_icache_inv,.-mn10300_local_icache_inv
115 ###############################################################################
117 # void mn10300_local_dcache_inv(void)
118 # Invalidate the entire dcache
120 ###############################################################################
121         ALIGN
122         .globl  mn10300_local_dcache_inv
123         .type   mn10300_local_dcache_inv,@function
124 mn10300_local_dcache_inv:
125         mov     CHCTR,a0
127         movhu   (a0),d0
128         btst    CHCTR_DCEN,d0
129         beq     mn10300_local_dcache_inv_end
131 #if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
132         LOCAL_CLI_SAVE(d1)
134         # disable the dcache
135         and     ~CHCTR_DCEN,d0
136         movhu   d0,(a0)
138         # and wait for it to calm down
139         setlb
140         movhu   (a0),d0
141         btst    CHCTR_DCBUSY,d0
142         lne
144         # invalidate
145         or      CHCTR_DCINV,d0
146         movhu   d0,(a0)
148         # wait for the cache to finish
149         mov     CHCTR,a0
150         setlb
151         movhu   (a0),d0
152         btst    CHCTR_DCBUSY,d0
153         lne
155         # and reenable it
156         and     ~CHCTR_DCINV,d0
157         or      CHCTR_DCEN,d0
158         movhu   d0,(a0)
159         movhu   (a0),d0
161         LOCAL_IRQ_RESTORE(d1)
162 #else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
163         # invalidate
164         or      CHCTR_DCINV,d0
165         movhu   d0,(a0)
166         movhu   (a0),d0
167 #endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
169 mn10300_local_dcache_inv_end:
170         ret     [],0
171         .size   mn10300_local_dcache_inv,.-mn10300_local_dcache_inv
173 ###############################################################################
175 # void mn10300_local_dcache_inv_range(unsigned long start, unsigned long end)
176 # void mn10300_local_dcache_inv_range2(unsigned long start, unsigned long size)
177 # void mn10300_local_dcache_inv_page(unsigned long start)
178 # Invalidate a range of addresses on a page in the dcache
180 ###############################################################################
181         ALIGN
182         .globl  mn10300_local_dcache_inv_page
183         .globl  mn10300_local_dcache_inv_range
184         .globl  mn10300_local_dcache_inv_range2
185         .type   mn10300_local_dcache_inv_page,@function
186         .type   mn10300_local_dcache_inv_range,@function
187         .type   mn10300_local_dcache_inv_range2,@function
188 mn10300_local_dcache_inv_page:
189         and     ~(PAGE_SIZE-1),d0
190         mov     PAGE_SIZE,d1
191 mn10300_local_dcache_inv_range2:
192         add     d0,d1
193 mn10300_local_dcache_inv_range:
194         # If we are in writeback mode we check the start and end alignments,
195         # and if they're not cacheline-aligned, we must flush any bits outside
196         # the range that share cachelines with stuff inside the range
197 #ifdef CONFIG_MN10300_CACHE_WBACK
198         btst    ~(L1_CACHE_BYTES-1),d0
199         bne     1f
200         btst    ~(L1_CACHE_BYTES-1),d1
201         beq     2f
203         bra     mn10300_local_dcache_flush_inv_range
205 #endif /* CONFIG_MN10300_CACHE_WBACK */
207         movm    [d2,d3,a2],(sp)
209         mov     CHCTR,a2
210         movhu   (a2),d2
211         btst    CHCTR_DCEN,d2
212         beq     mn10300_local_dcache_inv_range_end
214 #ifndef CONFIG_MN10300_CACHE_WBACK
215         and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0      # round start
216                                                                 # addr down
218         add     L1_CACHE_BYTES,d1               # round end addr up
219         and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
220 #endif /* !CONFIG_MN10300_CACHE_WBACK */
221         mov     d0,a1
223         clr     d2                              # we're going to clear tag RAM
224                                                 # entries
226         # read the tags from the tag RAM, and if they indicate a valid dirty
227         # cache line then invalidate that line
228         mov     DCACHE_TAG(0,0),a0
229         mov     a1,d0
230         and     L1_CACHE_TAG_ENTRY,d0
231         add     d0,a0                           # starting dcache tag RAM
232                                                 # access address
234         sub     a1,d1
235         lsr     L1_CACHE_SHIFT,d1               # total number of entries to
236                                                 # examine
238         and     ~(L1_CACHE_DISPARITY-1),a1      # determine comparator base
240 mn10300_local_dcache_inv_range_outer_loop:
241         LOCAL_CLI_SAVE(d3)
243         # disable the dcache
244         movhu   (a2),d0
245         and     ~CHCTR_DCEN,d0
246         movhu   d0,(a2)
248         # and wait for it to calm down
249         setlb
250         movhu   (a2),d0
251         btst    CHCTR_DCBUSY,d0
252         lne
254 mn10300_local_dcache_inv_range_loop:
256         # process the way 0 slot
257         mov     (L1_CACHE_WAYDISP*0,a0),d0      # read the tag in the way 0 slot
258         btst    L1_CACHE_TAG_VALID,d0
259         beq     mn10300_local_dcache_inv_range_skip_0   # jump if this cacheline
260                                                 # is not valid
262         xor     a1,d0
263         lsr     12,d0
264         bne     mn10300_local_dcache_inv_range_skip_0   # jump if not this cacheline
266         mov     d2,(L1_CACHE_WAYDISP*0,a0)      # kill the tag
268 mn10300_local_dcache_inv_range_skip_0:
270         # process the way 1 slot
271         mov     (L1_CACHE_WAYDISP*1,a0),d0      # read the tag in the way 1 slot
272         btst    L1_CACHE_TAG_VALID,d0
273         beq     mn10300_local_dcache_inv_range_skip_1   # jump if this cacheline
274                                                 # is not valid
276         xor     a1,d0
277         lsr     12,d0
278         bne     mn10300_local_dcache_inv_range_skip_1   # jump if not this cacheline
280         mov     d2,(L1_CACHE_WAYDISP*1,a0)      # kill the tag
282 mn10300_local_dcache_inv_range_skip_1:
284         # process the way 2 slot
285         mov     (L1_CACHE_WAYDISP*2,a0),d0      # read the tag in the way 2 slot
286         btst    L1_CACHE_TAG_VALID,d0
287         beq     mn10300_local_dcache_inv_range_skip_2   # jump if this cacheline
288                                                 # is not valid
290         xor     a1,d0
291         lsr     12,d0
292         bne     mn10300_local_dcache_inv_range_skip_2   # jump if not this cacheline
294         mov     d2,(L1_CACHE_WAYDISP*2,a0)      # kill the tag
296 mn10300_local_dcache_inv_range_skip_2:
298         # process the way 3 slot
299         mov     (L1_CACHE_WAYDISP*3,a0),d0      # read the tag in the way 3 slot
300         btst    L1_CACHE_TAG_VALID,d0
301         beq     mn10300_local_dcache_inv_range_skip_3   # jump if this cacheline
302                                                 # is not valid
304         xor     a1,d0
305         lsr     12,d0
306         bne     mn10300_local_dcache_inv_range_skip_3   # jump if not this cacheline
308         mov     d2,(L1_CACHE_WAYDISP*3,a0)      # kill the tag
310 mn10300_local_dcache_inv_range_skip_3:
312         # approx every N steps we re-enable the cache and see if there are any
313         # interrupts to be processed
314         # we also break out if we've reached the end of the loop
315         # (the bottom nibble of the count is zero in both cases)
316         add     L1_CACHE_BYTES,a0
317         add     L1_CACHE_BYTES,a1
318         and     ~L1_CACHE_WAYDISP,a0
319         add     -1,d1
320         btst    mn10300_local_dcache_inv_range_intr_interval,d1
321         bne     mn10300_local_dcache_inv_range_loop
323         # wait for the cache to finish what it's doing
324         setlb
325         movhu   (a2),d0
326         btst    CHCTR_DCBUSY,d0
327         lne
329         # and reenable it
330         or      CHCTR_DCEN,d0
331         movhu   d0,(a2)
332         movhu   (a2),d0
334         # re-enable interrupts
335         # - we don't bother with delay NOPs as we'll have enough instructions
336         #   before we disable interrupts again to give the interrupts a chance
337         #   to happen
338         LOCAL_IRQ_RESTORE(d3)
340         # go around again if the counter hasn't yet reached zero
341         add     0,d1
342         bne     mn10300_local_dcache_inv_range_outer_loop
344 mn10300_local_dcache_inv_range_end:
345         ret     [d2,d3,a2],12
346         .size   mn10300_local_dcache_inv_page,.-mn10300_local_dcache_inv_page
347         .size   mn10300_local_dcache_inv_range,.-mn10300_local_dcache_inv_range
348         .size   mn10300_local_dcache_inv_range2,.-mn10300_local_dcache_inv_range2