Commit | Line | Data |
---|---|---|
9731d237 AT |
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 |