diff options
Diffstat (limited to 'arch/mn10300/mm/cache-flush-by-reg.S')
-rw-r--r-- | arch/mn10300/mm/cache-flush-by-reg.S | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/arch/mn10300/mm/cache-flush-by-reg.S b/arch/mn10300/mm/cache-flush-by-reg.S new file mode 100644 index 000000000000..1dcae0211671 --- /dev/null +++ b/arch/mn10300/mm/cache-flush-by-reg.S | |||
@@ -0,0 +1,308 @@ | |||
1 | /* MN10300 CPU core caching routines, using indirect regs on cache controller | ||
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 | |||
12 | #include <linux/sys.h> | ||
13 | #include <linux/linkage.h> | ||
14 | #include <asm/smp.h> | ||
15 | #include <asm/page.h> | ||
16 | #include <asm/cache.h> | ||
17 | #include <asm/irqflags.h> | ||
18 | |||
19 | .am33_2 | ||
20 | |||
21 | #ifndef CONFIG_SMP | ||
22 | .globl mn10300_dcache_flush | ||
23 | .globl mn10300_dcache_flush_page | ||
24 | .globl mn10300_dcache_flush_range | ||
25 | .globl mn10300_dcache_flush_range2 | ||
26 | .globl mn10300_dcache_flush_inv | ||
27 | .globl mn10300_dcache_flush_inv_page | ||
28 | .globl mn10300_dcache_flush_inv_range | ||
29 | .globl mn10300_dcache_flush_inv_range2 | ||
30 | |||
31 | mn10300_dcache_flush = mn10300_local_dcache_flush | ||
32 | mn10300_dcache_flush_page = mn10300_local_dcache_flush_page | ||
33 | mn10300_dcache_flush_range = mn10300_local_dcache_flush_range | ||
34 | mn10300_dcache_flush_range2 = mn10300_local_dcache_flush_range2 | ||
35 | mn10300_dcache_flush_inv = mn10300_local_dcache_flush_inv | ||
36 | mn10300_dcache_flush_inv_page = mn10300_local_dcache_flush_inv_page | ||
37 | mn10300_dcache_flush_inv_range = mn10300_local_dcache_flush_inv_range | ||
38 | mn10300_dcache_flush_inv_range2 = mn10300_local_dcache_flush_inv_range2 | ||
39 | |||
40 | #endif /* !CONFIG_SMP */ | ||
41 | |||
42 | ############################################################################### | ||
43 | # | ||
44 | # void mn10300_local_dcache_flush(void) | ||
45 | # Flush the entire data cache back to RAM | ||
46 | # | ||
47 | ############################################################################### | ||
48 | ALIGN | ||
49 | .globl mn10300_local_dcache_flush | ||
50 | .type mn10300_local_dcache_flush,@function | ||
51 | mn10300_local_dcache_flush: | ||
52 | movhu (CHCTR),d0 | ||
53 | btst CHCTR_DCEN,d0 | ||
54 | beq mn10300_local_dcache_flush_end | ||
55 | |||
56 | mov DCPGCR,a0 | ||
57 | |||
58 | LOCAL_CLI_SAVE(d1) | ||
59 | |||
60 | # wait for busy bit of area purge | ||
61 | setlb | ||
62 | mov (a0),d0 | ||
63 | btst DCPGCR_DCPGBSY,d0 | ||
64 | lne | ||
65 | |||
66 | # set mask | ||
67 | clr d0 | ||
68 | mov d0,(DCPGMR) | ||
69 | |||
70 | # area purge | ||
71 | # | ||
72 | # DCPGCR = DCPGCR_DCP | ||
73 | # | ||
74 | mov DCPGCR_DCP,d0 | ||
75 | mov d0,(a0) | ||
76 | |||
77 | # wait for busy bit of area purge | ||
78 | setlb | ||
79 | mov (a0),d0 | ||
80 | btst DCPGCR_DCPGBSY,d0 | ||
81 | lne | ||
82 | |||
83 | LOCAL_IRQ_RESTORE(d1) | ||
84 | |||
85 | mn10300_local_dcache_flush_end: | ||
86 | ret [],0 | ||
87 | .size mn10300_local_dcache_flush,.-mn10300_local_dcache_flush | ||
88 | |||
89 | ############################################################################### | ||
90 | # | ||
91 | # void mn10300_local_dcache_flush_page(unsigned long start) | ||
92 | # void mn10300_local_dcache_flush_range(unsigned long start, unsigned long end) | ||
93 | # void mn10300_local_dcache_flush_range2(unsigned long start, unsigned long size) | ||
94 | # Flush a range of addresses on a page in the dcache | ||
95 | # | ||
96 | ############################################################################### | ||
97 | ALIGN | ||
98 | .globl mn10300_local_dcache_flush_page | ||
99 | .globl mn10300_local_dcache_flush_range | ||
100 | .globl mn10300_local_dcache_flush_range2 | ||
101 | .type mn10300_local_dcache_flush_page,@function | ||
102 | .type mn10300_local_dcache_flush_range,@function | ||
103 | .type mn10300_local_dcache_flush_range2,@function | ||
104 | mn10300_local_dcache_flush_page: | ||
105 | and ~(PAGE_SIZE-1),d0 | ||
106 | mov PAGE_SIZE,d1 | ||
107 | mn10300_local_dcache_flush_range2: | ||
108 | add d0,d1 | ||
109 | mn10300_local_dcache_flush_range: | ||
110 | movm [d2,d3,a2],(sp) | ||
111 | |||
112 | movhu (CHCTR),d2 | ||
113 | btst CHCTR_DCEN,d2 | ||
114 | beq mn10300_local_dcache_flush_range_end | ||
115 | |||
116 | # calculate alignsize | ||
117 | # | ||
118 | # alignsize = L1_CACHE_BYTES; | ||
119 | # for (i = (end - start - 1) / L1_CACHE_BYTES ; i > 0; i >>= 1) | ||
120 | # alignsize <<= 1; | ||
121 | # d2 = alignsize; | ||
122 | # | ||
123 | mov L1_CACHE_BYTES,d2 | ||
124 | sub d0,d1,d3 | ||
125 | add -1,d3 | ||
126 | lsr L1_CACHE_SHIFT,d3 | ||
127 | beq 2f | ||
128 | 1: | ||
129 | add d2,d2 | ||
130 | lsr 1,d3 | ||
131 | bne 1b | ||
132 | 2: | ||
133 | mov d1,a1 # a1 = end | ||
134 | |||
135 | LOCAL_CLI_SAVE(d3) | ||
136 | mov DCPGCR,a0 | ||
137 | |||
138 | # wait for busy bit of area purge | ||
139 | setlb | ||
140 | mov (a0),d1 | ||
141 | btst DCPGCR_DCPGBSY,d1 | ||
142 | lne | ||
143 | |||
144 | # determine the mask | ||
145 | mov d2,d1 | ||
146 | add -1,d1 | ||
147 | not d1 # d1 = mask = ~(alignsize-1) | ||
148 | mov d1,(DCPGMR) | ||
149 | |||
150 | and d1,d0,a2 # a2 = mask & start | ||
151 | |||
152 | dcpgloop: | ||
153 | # area purge | ||
154 | mov a2,d0 | ||
155 | or DCPGCR_DCP,d0 | ||
156 | mov d0,(a0) # DCPGCR = (mask & start) | DCPGCR_DCP | ||
157 | |||
158 | # wait for busy bit of area purge | ||
159 | setlb | ||
160 | mov (a0),d1 | ||
161 | btst DCPGCR_DCPGBSY,d1 | ||
162 | lne | ||
163 | |||
164 | # check purge of end address | ||
165 | add d2,a2 # a2 += alignsize | ||
166 | cmp a1,a2 # if (a2 < end) goto dcpgloop | ||
167 | bns dcpgloop | ||
168 | |||
169 | LOCAL_IRQ_RESTORE(d3) | ||
170 | |||
171 | mn10300_local_dcache_flush_range_end: | ||
172 | ret [d2,d3,a2],12 | ||
173 | |||
174 | .size mn10300_local_dcache_flush_page,.-mn10300_local_dcache_flush_page | ||
175 | .size mn10300_local_dcache_flush_range,.-mn10300_local_dcache_flush_range | ||
176 | .size mn10300_local_dcache_flush_range2,.-mn10300_local_dcache_flush_range2 | ||
177 | |||
178 | ############################################################################### | ||
179 | # | ||
180 | # void mn10300_local_dcache_flush_inv(void) | ||
181 | # Flush the entire data cache and invalidate all entries | ||
182 | # | ||
183 | ############################################################################### | ||
184 | ALIGN | ||
185 | .globl mn10300_local_dcache_flush_inv | ||
186 | .type mn10300_local_dcache_flush_inv,@function | ||
187 | mn10300_local_dcache_flush_inv: | ||
188 | movhu (CHCTR),d0 | ||
189 | btst CHCTR_DCEN,d0 | ||
190 | beq mn10300_local_dcache_flush_inv_end | ||
191 | |||
192 | mov DCPGCR,a0 | ||
193 | |||
194 | LOCAL_CLI_SAVE(d1) | ||
195 | |||
196 | # wait for busy bit of area purge & invalidate | ||
197 | setlb | ||
198 | mov (a0),d0 | ||
199 | btst DCPGCR_DCPGBSY,d0 | ||
200 | lne | ||
201 | |||
202 | # set the mask to cover everything | ||
203 | clr d0 | ||
204 | mov d0,(DCPGMR) | ||
205 | |||
206 | # area purge & invalidate | ||
207 | mov DCPGCR_DCP|DCPGCR_DCI,d0 | ||
208 | mov d0,(a0) | ||
209 | |||
210 | # wait for busy bit of area purge & invalidate | ||
211 | setlb | ||
212 | mov (a0),d0 | ||
213 | btst DCPGCR_DCPGBSY,d0 | ||
214 | lne | ||
215 | |||
216 | LOCAL_IRQ_RESTORE(d1) | ||
217 | |||
218 | mn10300_local_dcache_flush_inv_end: | ||
219 | ret [],0 | ||
220 | .size mn10300_local_dcache_flush_inv,.-mn10300_local_dcache_flush_inv | ||
221 | |||
222 | ############################################################################### | ||
223 | # | ||
224 | # void mn10300_local_dcache_flush_inv_page(unsigned long start) | ||
225 | # void mn10300_local_dcache_flush_inv_range(unsigned long start, unsigned long end) | ||
226 | # void mn10300_local_dcache_flush_inv_range2(unsigned long start, unsigned long size) | ||
227 | # Flush and invalidate a range of addresses on a page in the dcache | ||
228 | # | ||
229 | ############################################################################### | ||
230 | ALIGN | ||
231 | .globl mn10300_local_dcache_flush_inv_page | ||
232 | .globl mn10300_local_dcache_flush_inv_range | ||
233 | .globl mn10300_local_dcache_flush_inv_range2 | ||
234 | .type mn10300_local_dcache_flush_inv_page,@function | ||
235 | .type mn10300_local_dcache_flush_inv_range,@function | ||
236 | .type mn10300_local_dcache_flush_inv_range2,@function | ||
237 | mn10300_local_dcache_flush_inv_page: | ||
238 | and ~(PAGE_SIZE-1),d0 | ||
239 | mov PAGE_SIZE,d1 | ||
240 | mn10300_local_dcache_flush_inv_range2: | ||
241 | add d0,d1 | ||
242 | mn10300_local_dcache_flush_inv_range: | ||
243 | movm [d2,d3,a2],(sp) | ||
244 | |||
245 | movhu (CHCTR),d2 | ||
246 | btst CHCTR_DCEN,d2 | ||
247 | beq mn10300_local_dcache_flush_inv_range_end | ||
248 | |||
249 | # calculate alignsize | ||
250 | # | ||
251 | # alignsize = L1_CACHE_BYTES; | ||
252 | # for (i = (end - start - 1) / L1_CACHE_BYTES; i > 0; i >>= 1) | ||
253 | # alignsize <<= 1; | ||
254 | # d2 = alignsize | ||
255 | # | ||
256 | mov L1_CACHE_BYTES,d2 | ||
257 | sub d0,d1,d3 | ||
258 | add -1,d3 | ||
259 | lsr L1_CACHE_SHIFT,d3 | ||
260 | beq 2f | ||
261 | 1: | ||
262 | add d2,d2 | ||
263 | lsr 1,d3 | ||
264 | bne 1b | ||
265 | 2: | ||
266 | mov d1,a1 # a1 = end | ||
267 | |||
268 | LOCAL_CLI_SAVE(d3) | ||
269 | mov DCPGCR,a0 | ||
270 | |||
271 | # wait for busy bit of area purge & invalidate | ||
272 | setlb | ||
273 | mov (a0),d1 | ||
274 | btst DCPGCR_DCPGBSY,d1 | ||
275 | lne | ||
276 | |||
277 | # set the mask | ||
278 | mov d2,d1 | ||
279 | add -1,d1 | ||
280 | not d1 # d1 = mask = ~(alignsize-1) | ||
281 | mov d1,(DCPGMR) | ||
282 | |||
283 | and d1,d0,a2 # a2 = mask & start | ||
284 | |||
285 | dcpgivloop: | ||
286 | # area purge & invalidate | ||
287 | mov a2,d0 | ||
288 | or DCPGCR_DCP|DCPGCR_DCI,d0 | ||
289 | mov d0,(a0) # DCPGCR = (mask & start)|DCPGCR_DCP|DCPGCR_DCI | ||
290 | |||
291 | # wait for busy bit of area purge & invalidate | ||
292 | setlb | ||
293 | mov (a0),d1 | ||
294 | btst DCPGCR_DCPGBSY,d1 | ||
295 | lne | ||
296 | |||
297 | # check purge & invalidate of end address | ||
298 | add d2,a2 # a2 += alignsize | ||
299 | cmp a1,a2 # if (a2 < end) goto dcpgivloop | ||
300 | bns dcpgivloop | ||
301 | |||
302 | LOCAL_IRQ_RESTORE(d3) | ||
303 | |||
304 | mn10300_local_dcache_flush_inv_range_end: | ||
305 | ret [d2,d3,a2],12 | ||
306 | .size mn10300_local_dcache_flush_inv_page,.-mn10300_local_dcache_flush_inv_page | ||
307 | .size mn10300_local_dcache_flush_inv_range,.-mn10300_local_dcache_flush_inv_range | ||
308 | .size mn10300_local_dcache_flush_inv_range2,.-mn10300_local_dcache_flush_inv_range2 | ||