blob: 1dcae0211671db7362bd7bd85aa62961039f1f2d [file] [log] [blame]
Akira Takeuchi9731d232010-10-27 17:28:45 +01001/* 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
31mn10300_dcache_flush = mn10300_local_dcache_flush
32mn10300_dcache_flush_page = mn10300_local_dcache_flush_page
33mn10300_dcache_flush_range = mn10300_local_dcache_flush_range
34mn10300_dcache_flush_range2 = mn10300_local_dcache_flush_range2
35mn10300_dcache_flush_inv = mn10300_local_dcache_flush_inv
36mn10300_dcache_flush_inv_page = mn10300_local_dcache_flush_inv_page
37mn10300_dcache_flush_inv_range = mn10300_local_dcache_flush_inv_range
38mn10300_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
51mn10300_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
85mn10300_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
104mn10300_local_dcache_flush_page:
105 and ~(PAGE_SIZE-1),d0
106 mov PAGE_SIZE,d1
107mn10300_local_dcache_flush_range2:
108 add d0,d1
109mn10300_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
1281:
129 add d2,d2
130 lsr 1,d3
131 bne 1b
1322:
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
152dcpgloop:
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
171mn10300_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
187mn10300_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
218mn10300_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
237mn10300_local_dcache_flush_inv_page:
238 and ~(PAGE_SIZE-1),d0
239 mov PAGE_SIZE,d1
240mn10300_local_dcache_flush_inv_range2:
241 add d0,d1
242mn10300_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
2611:
262 add d2,d2
263 lsr 1,d3
264 bne 1b
2652:
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
285dcpgivloop:
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
304mn10300_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