Merge branch 'smsc47b397-new-id' into release
[linux-2.6] / arch / mn10300 / mm / cache-mn10300.S
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
17 #define mn10300_dcache_inv_range_intr_interval \
18         +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
19
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
23
24         .am33_2
25
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
31
32 ###############################################################################
33 #
34 # void mn10300_icache_inv(void)
35 # Invalidate the entire icache
36 #
37 ###############################################################################
38         ALIGN
39 mn10300_icache_inv:
40         mov     CHCTR,a0
41
42         movhu   (a0),d0
43         btst    CHCTR_ICEN,d0
44         beq     mn10300_icache_inv_end
45
46         mov     epsw,d1
47         and     ~EPSW_IE,epsw
48         nop
49         nop
50
51         # disable the icache
52         and     ~CHCTR_ICEN,d0
53         movhu   d0,(a0)
54
55         # and wait for it to calm down
56         setlb
57         movhu   (a0),d0
58         btst    CHCTR_ICBUSY,d0
59         lne
60
61         # invalidate
62         or      CHCTR_ICINV,d0
63         movhu   d0,(a0)
64
65         # wait for the cache to finish
66         mov     CHCTR,a0
67         setlb
68         movhu   (a0),d0
69         btst    CHCTR_ICBUSY,d0
70         lne
71
72         # and reenable it
73         and     ~CHCTR_ICINV,d0
74         or      CHCTR_ICEN,d0
75         movhu   d0,(a0)
76         movhu   (a0),d0
77
78         mov     d1,epsw
79
80 mn10300_icache_inv_end:
81         ret     [],0
82
83 ###############################################################################
84 #
85 # void mn10300_dcache_inv(void)
86 # Invalidate the entire dcache
87 #
88 ###############################################################################
89         ALIGN
90 mn10300_dcache_inv:
91         mov     CHCTR,a0
92
93         movhu   (a0),d0
94         btst    CHCTR_DCEN,d0
95         beq     mn10300_dcache_inv_end
96
97         mov     epsw,d1
98         and     ~EPSW_IE,epsw
99         nop
100         nop
101
102         # disable the dcache
103         and     ~CHCTR_DCEN,d0
104         movhu   d0,(a0)
105
106         # and wait for it to calm down
107         setlb
108         movhu   (a0),d0
109         btst    CHCTR_DCBUSY,d0
110         lne
111
112         # invalidate
113         or      CHCTR_DCINV,d0
114         movhu   d0,(a0)
115
116         # wait for the cache to finish
117         mov     CHCTR,a0
118         setlb
119         movhu   (a0),d0
120         btst    CHCTR_DCBUSY,d0
121         lne
122
123         # and reenable it
124         and     ~CHCTR_DCINV,d0
125         or      CHCTR_DCEN,d0
126         movhu   d0,(a0)
127         movhu   (a0),d0
128
129         mov     d1,epsw
130
131 mn10300_dcache_inv_end:
132         ret     [],0
133
134 ###############################################################################
135 #
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
140 #
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
150
151         movhu   (a2),d2
152         btst    CHCTR_DCEN,d2
153         beq     mn10300_dcache_inv_range_end
154
155         and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0      # round start
156                                                                 # addr down
157         mov     d0,a1
158
159         add     L1_CACHE_BYTES,d1                       # round end addr up
160         and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
161
162         clr     d2                              # we're going to clear tag ram
163                                                 # entries
164
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
172
173         sub     a1,d1
174         lsr     L1_CACHE_SHIFT,d1               # total number of entries to
175                                                 # examine
176
177         and     ~(L1_CACHE_DISPARITY-1),a1      # determine comparator base
178
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
187
188         # disable the dcache
189         movhu   (a2),d0
190         and     ~CHCTR_DCEN,d0
191         movhu   d0,(a2)
192
193         # and wait for it to calm down
194         setlb
195         movhu   (a2),d0
196         btst    CHCTR_DCBUSY,d0
197         lne
198
199 mn10300_dcache_inv_range_loop:
200
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
206
207         xor     a1,d0
208         lsr     12,d0
209         bne     mn10300_dcache_inv_range_skip_0 # jump if not this cacheline
210
211         mov     d2,(a0)                         # kill the tag
212
213 mn10300_dcache_inv_range_skip_0:
214
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
220
221         xor     a1,d0
222         lsr     12,d0
223         bne     mn10300_dcache_inv_range_skip_1 # jump if not this cacheline
224
225         mov     d2,(a0)                         # kill the tag
226
227 mn10300_dcache_inv_range_skip_1:
228
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
234
235         xor     a1,d0
236         lsr     12,d0
237         bne     mn10300_dcache_inv_range_skip_2 # jump if not this cacheline
238
239         mov     d2,(a0)                         # kill the tag
240
241 mn10300_dcache_inv_range_skip_2:
242
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
248
249         xor     a1,d0
250         lsr     12,d0
251         bne     mn10300_dcache_inv_range_skip_3 # jump if not this cacheline
252
253         mov     d2,(a0)                         # kill the tag
254
255 mn10300_dcache_inv_range_skip_3:
256
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
266
267         # wait for the cache to finish what it's doing
268         setlb
269         movhu   (a2),d0
270         btst    CHCTR_DCBUSY,d0
271         lne
272
273         # and reenable it
274         or      CHCTR_DCEN,d0
275         movhu   d0,(a2)
276         movhu   (a2),d0
277
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
283
284         # go around again if the counter hasn't yet reached zero
285         add     0,d1
286         bne     mn10300_dcache_inv_range_outer_loop
287
288 mn10300_dcache_inv_range_end:
289         ret     [d2,d3,a2],12