Linux 2.6.31.6
[linux/fpc-iii.git] / arch / mn10300 / mm / cache-mn10300.S
blobe839d0aedd69f953625d566d08255bfd5d07cf51
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>
17 #define mn10300_dcache_inv_range_intr_interval \
18         +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
20 #if mn10300_dcache_inv_range_intr_interval > 0xff
21 #error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less
22 #endif
24         .am33_2
26         .globl mn10300_icache_inv
27         .globl mn10300_dcache_inv
28         .globl mn10300_dcache_inv_range
29         .globl mn10300_dcache_inv_range2
30         .globl mn10300_dcache_inv_page
32 ###############################################################################
34 # void mn10300_icache_inv(void)
35 # Invalidate the entire icache
37 ###############################################################################
38         ALIGN
39 mn10300_icache_inv:
40         mov     CHCTR,a0
42         movhu   (a0),d0
43         btst    CHCTR_ICEN,d0
44         beq     mn10300_icache_inv_end
46         mov     epsw,d1
47         and     ~EPSW_IE,epsw
48         nop
49         nop
51         # disable the icache
52         and     ~CHCTR_ICEN,d0
53         movhu   d0,(a0)
55         # and wait for it to calm down
56         setlb
57         movhu   (a0),d0
58         btst    CHCTR_ICBUSY,d0
59         lne
61         # invalidate
62         or      CHCTR_ICINV,d0
63         movhu   d0,(a0)
65         # wait for the cache to finish
66         mov     CHCTR,a0
67         setlb
68         movhu   (a0),d0
69         btst    CHCTR_ICBUSY,d0
70         lne
72         # and reenable it
73         and     ~CHCTR_ICINV,d0
74         or      CHCTR_ICEN,d0
75         movhu   d0,(a0)
76         movhu   (a0),d0
78         mov     d1,epsw
80 mn10300_icache_inv_end:
81         ret     [],0
83 ###############################################################################
85 # void mn10300_dcache_inv(void)
86 # Invalidate the entire dcache
88 ###############################################################################
89         ALIGN
90 mn10300_dcache_inv:
91         mov     CHCTR,a0
93         movhu   (a0),d0
94         btst    CHCTR_DCEN,d0
95         beq     mn10300_dcache_inv_end
97         mov     epsw,d1
98         and     ~EPSW_IE,epsw
99         nop
100         nop
102         # disable the dcache
103         and     ~CHCTR_DCEN,d0
104         movhu   d0,(a0)
106         # and wait for it to calm down
107         setlb
108         movhu   (a0),d0
109         btst    CHCTR_DCBUSY,d0
110         lne
112         # invalidate
113         or      CHCTR_DCINV,d0
114         movhu   d0,(a0)
116         # wait for the cache to finish
117         mov     CHCTR,a0
118         setlb
119         movhu   (a0),d0
120         btst    CHCTR_DCBUSY,d0
121         lne
123         # and reenable it
124         and     ~CHCTR_DCINV,d0
125         or      CHCTR_DCEN,d0
126         movhu   d0,(a0)
127         movhu   (a0),d0
129         mov     d1,epsw
131 mn10300_dcache_inv_end:
132         ret     [],0
134 ###############################################################################
136 # void mn10300_dcache_inv_range(unsigned start, unsigned end)
137 # void mn10300_dcache_inv_range2(unsigned start, unsigned size)
138 # void mn10300_dcache_inv_page(unsigned start)
139 # Invalidate a range of addresses on a page in the dcache
141 ###############################################################################
142         ALIGN
143 mn10300_dcache_inv_page:
144         mov     PAGE_SIZE,d1
145 mn10300_dcache_inv_range2:
146         add     d0,d1
147 mn10300_dcache_inv_range:
148         movm    [d2,d3,a2],(sp)
149         mov     CHCTR,a2
151         movhu   (a2),d2
152         btst    CHCTR_DCEN,d2
153         beq     mn10300_dcache_inv_range_end
155         and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0      # round start
156                                                                 # addr down
157         mov     d0,a1
159         add     L1_CACHE_BYTES,d1                       # round end addr up
160         and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
162         clr     d2                              # we're going to clear tag ram
163                                                 # entries
165         # read the tags from the tag RAM, and if they indicate a valid dirty
166         # cache line then invalidate that line
167         mov     DCACHE_TAG(0,0),a0
168         mov     a1,d0
169         and     L1_CACHE_TAG_ENTRY,d0
170         add     d0,a0                           # starting dcache tag RAM
171                                                 # access address
173         sub     a1,d1
174         lsr     L1_CACHE_SHIFT,d1               # total number of entries to
175                                                 # examine
177         and     ~(L1_CACHE_DISPARITY-1),a1      # determine comparator base
179 mn10300_dcache_inv_range_outer_loop:
180         # disable interrupts
181         mov     epsw,d3
182         and     ~EPSW_IE,epsw
183         nop                                     # note that reading CHCTR and
184                                                 # AND'ing D0 occupy two delay
185                                                 # slots after disabling
186                                                 # interrupts
188         # disable the dcache
189         movhu   (a2),d0
190         and     ~CHCTR_DCEN,d0
191         movhu   d0,(a2)
193         # and wait for it to calm down
194         setlb
195         movhu   (a2),d0
196         btst    CHCTR_DCBUSY,d0
197         lne
199 mn10300_dcache_inv_range_loop:
201         # process the way 0 slot
202         mov     (L1_CACHE_WAYDISP*0,a0),d0      # read the tag in the way 0 slot
203         btst    L1_CACHE_TAG_VALID,d0
204         beq     mn10300_dcache_inv_range_skip_0 # jump if this cacheline is not
205                                                 # valid
207         xor     a1,d0
208         lsr     12,d0
209         bne     mn10300_dcache_inv_range_skip_0 # jump if not this cacheline
211         mov     d2,(a0)                         # kill the tag
213 mn10300_dcache_inv_range_skip_0:
215         # process the way 1 slot
216         mov     (L1_CACHE_WAYDISP*1,a0),d0      # read the tag in the way 1 slot
217         btst    L1_CACHE_TAG_VALID,d0
218         beq     mn10300_dcache_inv_range_skip_1 # jump if this cacheline is not
219                                                 # valid
221         xor     a1,d0
222         lsr     12,d0
223         bne     mn10300_dcache_inv_range_skip_1 # jump if not this cacheline
225         mov     d2,(a0)                         # kill the tag
227 mn10300_dcache_inv_range_skip_1:
229         # process the way 2 slot
230         mov     (L1_CACHE_WAYDISP*2,a0),d0      # read the tag in the way 2 slot
231         btst    L1_CACHE_TAG_VALID,d0
232         beq     mn10300_dcache_inv_range_skip_2 # jump if this cacheline is not
233                                                 # valid
235         xor     a1,d0
236         lsr     12,d0
237         bne     mn10300_dcache_inv_range_skip_2 # jump if not this cacheline
239         mov     d2,(a0)                         # kill the tag
241 mn10300_dcache_inv_range_skip_2:
243         # process the way 3 slot
244         mov     (L1_CACHE_WAYDISP*3,a0),d0      # read the tag in the way 3 slot
245         btst    L1_CACHE_TAG_VALID,d0
246         beq     mn10300_dcache_inv_range_skip_3 # jump if this cacheline is not
247                                                 # valid
249         xor     a1,d0
250         lsr     12,d0
251         bne     mn10300_dcache_inv_range_skip_3 # jump if not this cacheline
253         mov     d2,(a0)                         # kill the tag
255 mn10300_dcache_inv_range_skip_3:
257         # approx every N steps we re-enable the cache and see if there are any
258         # interrupts to be processed
259         # we also break out if we've reached the end of the loop
260         # (the bottom nibble of the count is zero in both cases)
261         add     L1_CACHE_BYTES,a0
262         add     L1_CACHE_BYTES,a1
263         add     -1,d1
264         btst    mn10300_dcache_inv_range_intr_interval,d1
265         bne     mn10300_dcache_inv_range_loop
267         # wait for the cache to finish what it's doing
268         setlb
269         movhu   (a2),d0
270         btst    CHCTR_DCBUSY,d0
271         lne
273         # and reenable it
274         or      CHCTR_DCEN,d0
275         movhu   d0,(a2)
276         movhu   (a2),d0
278         # re-enable interrupts
279         # - we don't bother with delay NOPs as we'll have enough instructions
280         #   before we disable interrupts again to give the interrupts a chance
281         #   to happen
282         mov     d3,epsw
284         # go around again if the counter hasn't yet reached zero
285         add     0,d1
286         bne     mn10300_dcache_inv_range_outer_loop
288 mn10300_dcache_inv_range_end:
289         ret     [d2,d3,a2],12