diff options
-rw-r--r-- | arch/mn10300/mm/Kconfig.cache | 13 | ||||
-rw-r--r-- | arch/mn10300/mm/Makefile | 2 | ||||
-rw-r--r-- | arch/mn10300/mm/cache-flush-by-reg.S | 308 | ||||
-rw-r--r-- | arch/mn10300/mm/cache-inv-by-reg.S | 356 |
4 files changed, 678 insertions, 1 deletions
diff --git a/arch/mn10300/mm/Kconfig.cache b/arch/mn10300/mm/Kconfig.cache index aa6ff0791138..97adc06e7128 100644 --- a/arch/mn10300/mm/Kconfig.cache +++ b/arch/mn10300/mm/Kconfig.cache | |||
@@ -37,7 +37,8 @@ config MN10300_CACHE_ENABLED | |||
37 | 37 | ||
38 | choice | 38 | choice |
39 | prompt "CPU cache flush/invalidate method" | 39 | prompt "CPU cache flush/invalidate method" |
40 | default MN10300_CACHE_MANAGE_BY_TAG | 40 | default MN10300_CACHE_MANAGE_BY_TAG if !AM34_2 |
41 | default MN10300_CACHE_MANAGE_BY_REG if AM34_2 | ||
41 | depends on MN10300_CACHE_ENABLED | 42 | depends on MN10300_CACHE_ENABLED |
42 | help | 43 | help |
43 | This determines the method by which CPU cache flushing and | 44 | This determines the method by which CPU cache flushing and |
@@ -46,10 +47,20 @@ choice | |||
46 | config MN10300_CACHE_MANAGE_BY_TAG | 47 | config MN10300_CACHE_MANAGE_BY_TAG |
47 | bool "Use the cache tag registers directly" | 48 | bool "Use the cache tag registers directly" |
48 | 49 | ||
50 | config MN10300_CACHE_MANAGE_BY_REG | ||
51 | bool "Flush areas by way of automatic purge registers (AM34 only)" | ||
52 | depends on AM34_2 | ||
53 | |||
49 | endchoice | 54 | endchoice |
50 | 55 | ||
51 | config MN10300_CACHE_INV_BY_TAG | 56 | config MN10300_CACHE_INV_BY_TAG |
52 | def_bool y if MN10300_CACHE_MANAGE_BY_TAG && MN10300_CACHE_ENABLED | 57 | def_bool y if MN10300_CACHE_MANAGE_BY_TAG && MN10300_CACHE_ENABLED |
53 | 58 | ||
59 | config MN10300_CACHE_INV_BY_REG | ||
60 | def_bool y if MN10300_CACHE_MANAGE_BY_REG && MN10300_CACHE_ENABLED | ||
61 | |||
54 | config MN10300_CACHE_FLUSH_BY_TAG | 62 | config MN10300_CACHE_FLUSH_BY_TAG |
55 | def_bool y if MN10300_CACHE_MANAGE_BY_TAG && MN10300_CACHE_WBACK | 63 | def_bool y if MN10300_CACHE_MANAGE_BY_TAG && MN10300_CACHE_WBACK |
64 | |||
65 | config MN10300_CACHE_FLUSH_BY_REG | ||
66 | def_bool y if MN10300_CACHE_MANAGE_BY_REG && MN10300_CACHE_WBACK | ||
diff --git a/arch/mn10300/mm/Makefile b/arch/mn10300/mm/Makefile index dc4b9f0ea65c..7b997236ed20 100644 --- a/arch/mn10300/mm/Makefile +++ b/arch/mn10300/mm/Makefile | |||
@@ -4,7 +4,9 @@ | |||
4 | 4 | ||
5 | cacheflush-y := cache.o | 5 | cacheflush-y := cache.o |
6 | cacheflush-$(CONFIG_MN10300_CACHE_INV_BY_TAG) += cache-inv-by-tag.o | 6 | cacheflush-$(CONFIG_MN10300_CACHE_INV_BY_TAG) += cache-inv-by-tag.o |
7 | cacheflush-$(CONFIG_MN10300_CACHE_INV_BY_REG) += cache-inv-by-reg.o | ||
7 | cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_TAG) += cache-flush-by-tag.o | 8 | cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_TAG) += cache-flush-by-tag.o |
9 | cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_REG) += cache-flush-by-reg.o | ||
8 | 10 | ||
9 | cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o | 11 | cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o |
10 | 12 | ||
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 | ||
diff --git a/arch/mn10300/mm/cache-inv-by-reg.S b/arch/mn10300/mm/cache-inv-by-reg.S new file mode 100644 index 000000000000..c8950861ed77 --- /dev/null +++ b/arch/mn10300/mm/cache-inv-by-reg.S | |||
@@ -0,0 +1,356 @@ | |||
1 | /* MN10300 CPU cache invalidation routines, using automatic purge registers | ||
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 | #include <asm/irqflags.h> | ||
17 | #include <asm/cacheflush.h> | ||
18 | |||
19 | #define mn10300_local_dcache_inv_range_intr_interval \ | ||
20 | +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1) | ||
21 | |||
22 | #if mn10300_local_dcache_inv_range_intr_interval > 0xff | ||
23 | #error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less | ||
24 | #endif | ||
25 | |||
26 | .am33_2 | ||
27 | |||
28 | #ifndef CONFIG_SMP | ||
29 | .globl mn10300_icache_inv | ||
30 | .globl mn10300_icache_inv_page | ||
31 | .globl mn10300_icache_inv_range | ||
32 | .globl mn10300_icache_inv_range2 | ||
33 | .globl mn10300_dcache_inv | ||
34 | .globl mn10300_dcache_inv_page | ||
35 | .globl mn10300_dcache_inv_range | ||
36 | .globl mn10300_dcache_inv_range2 | ||
37 | |||
38 | mn10300_icache_inv = mn10300_local_icache_inv | ||
39 | mn10300_icache_inv_page = mn10300_local_icache_inv_page | ||
40 | mn10300_icache_inv_range = mn10300_local_icache_inv_range | ||
41 | mn10300_icache_inv_range2 = mn10300_local_icache_inv_range2 | ||
42 | mn10300_dcache_inv = mn10300_local_dcache_inv | ||
43 | mn10300_dcache_inv_page = mn10300_local_dcache_inv_page | ||
44 | mn10300_dcache_inv_range = mn10300_local_dcache_inv_range | ||
45 | mn10300_dcache_inv_range2 = mn10300_local_dcache_inv_range2 | ||
46 | |||
47 | #endif /* !CONFIG_SMP */ | ||
48 | |||
49 | ############################################################################### | ||
50 | # | ||
51 | # void mn10300_local_icache_inv(void) | ||
52 | # Invalidate the entire icache | ||
53 | # | ||
54 | ############################################################################### | ||
55 | ALIGN | ||
56 | .globl mn10300_local_icache_inv | ||
57 | .type mn10300_local_icache_inv,@function | ||
58 | mn10300_local_icache_inv: | ||
59 | mov CHCTR,a0 | ||
60 | |||
61 | movhu (a0),d0 | ||
62 | btst CHCTR_ICEN,d0 | ||
63 | beq mn10300_local_icache_inv_end | ||
64 | |||
65 | # invalidate | ||
66 | or CHCTR_ICINV,d0 | ||
67 | movhu d0,(a0) | ||
68 | movhu (a0),d0 | ||
69 | |||
70 | mn10300_local_icache_inv_end: | ||
71 | ret [],0 | ||
72 | .size mn10300_local_icache_inv,.-mn10300_local_icache_inv | ||
73 | |||
74 | ############################################################################### | ||
75 | # | ||
76 | # void mn10300_local_dcache_inv(void) | ||
77 | # Invalidate the entire dcache | ||
78 | # | ||
79 | ############################################################################### | ||
80 | ALIGN | ||
81 | .globl mn10300_local_dcache_inv | ||
82 | .type mn10300_local_dcache_inv,@function | ||
83 | mn10300_local_dcache_inv: | ||
84 | mov CHCTR,a0 | ||
85 | |||
86 | movhu (a0),d0 | ||
87 | btst CHCTR_DCEN,d0 | ||
88 | beq mn10300_local_dcache_inv_end | ||
89 | |||
90 | # invalidate | ||
91 | or CHCTR_DCINV,d0 | ||
92 | movhu d0,(a0) | ||
93 | movhu (a0),d0 | ||
94 | |||
95 | mn10300_local_dcache_inv_end: | ||
96 | ret [],0 | ||
97 | .size mn10300_local_dcache_inv,.-mn10300_local_dcache_inv | ||
98 | |||
99 | ############################################################################### | ||
100 | # | ||
101 | # void mn10300_local_dcache_inv_range(unsigned long start, unsigned long end) | ||
102 | # void mn10300_local_dcache_inv_range2(unsigned long start, unsigned long size) | ||
103 | # void mn10300_local_dcache_inv_page(unsigned long start) | ||
104 | # Invalidate a range of addresses on a page in the dcache | ||
105 | # | ||
106 | ############################################################################### | ||
107 | ALIGN | ||
108 | .globl mn10300_local_dcache_inv_page | ||
109 | .globl mn10300_local_dcache_inv_range | ||
110 | .globl mn10300_local_dcache_inv_range2 | ||
111 | .type mn10300_local_dcache_inv_page,@function | ||
112 | .type mn10300_local_dcache_inv_range,@function | ||
113 | .type mn10300_local_dcache_inv_range2,@function | ||
114 | mn10300_local_dcache_inv_page: | ||
115 | and ~(PAGE_SIZE-1),d0 | ||
116 | mov PAGE_SIZE,d1 | ||
117 | mn10300_local_dcache_inv_range2: | ||
118 | add d0,d1 | ||
119 | mn10300_local_dcache_inv_range: | ||
120 | # If we are in writeback mode we check the start and end alignments, | ||
121 | # and if they're not cacheline-aligned, we must flush any bits outside | ||
122 | # the range that share cachelines with stuff inside the range | ||
123 | #ifdef CONFIG_MN10300_CACHE_WBACK | ||
124 | btst ~(L1_CACHE_BYTES-1),d0 | ||
125 | bne 1f | ||
126 | btst ~(L1_CACHE_BYTES-1),d1 | ||
127 | beq 2f | ||
128 | 1: | ||
129 | bra mn10300_local_dcache_flush_inv_range | ||
130 | 2: | ||
131 | #endif /* CONFIG_MN10300_CACHE_WBACK */ | ||
132 | |||
133 | movm [d2,d3,a2],(sp) | ||
134 | |||
135 | mov CHCTR,a0 | ||
136 | movhu (a0),d2 | ||
137 | btst CHCTR_DCEN,d2 | ||
138 | beq mn10300_local_dcache_inv_range_end | ||
139 | |||
140 | # round the addresses out to be full cachelines, unless we're in | ||
141 | # writeback mode, in which case we would be in flush and invalidate by | ||
142 | # now | ||
143 | #ifndef CONFIG_MN10300_CACHE_WBACK | ||
144 | and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 # round start | ||
145 | # addr down | ||
146 | |||
147 | mov L1_CACHE_BYTES-1,d2 | ||
148 | add d2,d1 | ||
149 | and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1 # round end addr up | ||
150 | #endif /* !CONFIG_MN10300_CACHE_WBACK */ | ||
151 | |||
152 | sub d0,d1,d2 # calculate the total size | ||
153 | mov d0,a2 # A2 = start address | ||
154 | mov d1,a1 # A1 = end address | ||
155 | |||
156 | LOCAL_CLI_SAVE(d3) | ||
157 | |||
158 | mov DCPGCR,a0 # make sure the purger isn't busy | ||
159 | setlb | ||
160 | mov (a0),d0 | ||
161 | btst DCPGCR_DCPGBSY,d0 | ||
162 | lne | ||
163 | |||
164 | # skip initial address alignment calculation if address is zero | ||
165 | mov d2,d1 | ||
166 | cmp 0,a2 | ||
167 | beq 1f | ||
168 | |||
169 | dcivloop: | ||
170 | /* calculate alignsize | ||
171 | * | ||
172 | * alignsize = L1_CACHE_BYTES; | ||
173 | * while (! start & alignsize) { | ||
174 | * alignsize <<=1; | ||
175 | * } | ||
176 | * d1 = alignsize; | ||
177 | */ | ||
178 | mov L1_CACHE_BYTES,d1 | ||
179 | lsr 1,d1 | ||
180 | setlb | ||
181 | add d1,d1 | ||
182 | mov d1,d0 | ||
183 | and a2,d0 | ||
184 | leq | ||
185 | |||
186 | 1: | ||
187 | /* calculate invsize | ||
188 | * | ||
189 | * if (totalsize > alignsize) { | ||
190 | * invsize = alignsize; | ||
191 | * } else { | ||
192 | * invsize = totalsize; | ||
193 | * tmp = 0x80000000; | ||
194 | * while (! invsize & tmp) { | ||
195 | * tmp >>= 1; | ||
196 | * } | ||
197 | * invsize = tmp; | ||
198 | * } | ||
199 | * d1 = invsize | ||
200 | */ | ||
201 | cmp d2,d1 | ||
202 | bns 2f | ||
203 | mov d2,d1 | ||
204 | |||
205 | mov 0x80000000,d0 # start from 31bit=1 | ||
206 | setlb | ||
207 | lsr 1,d0 | ||
208 | mov d0,e0 | ||
209 | and d1,e0 | ||
210 | leq | ||
211 | mov d0,d1 | ||
212 | |||
213 | 2: | ||
214 | /* set mask | ||
215 | * | ||
216 | * mask = ~(invsize-1); | ||
217 | * DCPGMR = mask; | ||
218 | */ | ||
219 | mov d1,d0 | ||
220 | add -1,d0 | ||
221 | not d0 | ||
222 | mov d0,(DCPGMR) | ||
223 | |||
224 | # invalidate area | ||
225 | mov a2,d0 | ||
226 | or DCPGCR_DCI,d0 | ||
227 | mov d0,(a0) # DCPGCR = (mask & start) | DCPGCR_DCI | ||
228 | |||
229 | setlb # wait for the purge to complete | ||
230 | mov (a0),d0 | ||
231 | btst DCPGCR_DCPGBSY,d0 | ||
232 | lne | ||
233 | |||
234 | sub d1,d2 # decrease size remaining | ||
235 | add d1,a2 # increase next start address | ||
236 | |||
237 | /* check invalidating of end address | ||
238 | * | ||
239 | * a2 = a2 + invsize | ||
240 | * if (a2 < end) { | ||
241 | * goto dcivloop; | ||
242 | * } */ | ||
243 | cmp a1,a2 | ||
244 | bns dcivloop | ||
245 | |||
246 | LOCAL_IRQ_RESTORE(d3) | ||
247 | |||
248 | mn10300_local_dcache_inv_range_end: | ||
249 | ret [d2,d3,a2],12 | ||
250 | .size mn10300_local_dcache_inv_page,.-mn10300_local_dcache_inv_page | ||
251 | .size mn10300_local_dcache_inv_range,.-mn10300_local_dcache_inv_range | ||
252 | .size mn10300_local_dcache_inv_range2,.-mn10300_local_dcache_inv_range2 | ||
253 | |||
254 | ############################################################################### | ||
255 | # | ||
256 | # void mn10300_local_icache_inv_page(unsigned long start) | ||
257 | # void mn10300_local_icache_inv_range2(unsigned long start, unsigned long size) | ||
258 | # void mn10300_local_icache_inv_range(unsigned long start, unsigned long end) | ||
259 | # Invalidate a range of addresses on a page in the icache | ||
260 | # | ||
261 | ############################################################################### | ||
262 | ALIGN | ||
263 | .globl mn10300_local_icache_inv_page | ||
264 | .globl mn10300_local_icache_inv_range | ||
265 | .globl mn10300_local_icache_inv_range2 | ||
266 | .type mn10300_local_icache_inv_page,@function | ||
267 | .type mn10300_local_icache_inv_range,@function | ||
268 | .type mn10300_local_icache_inv_range2,@function | ||
269 | mn10300_local_icache_inv_page: | ||
270 | and ~(PAGE_SIZE-1),d0 | ||
271 | mov PAGE_SIZE,d1 | ||
272 | mn10300_local_icache_inv_range2: | ||
273 | add d0,d1 | ||
274 | mn10300_local_icache_inv_range: | ||
275 | movm [d2,d3,a2],(sp) | ||
276 | |||
277 | mov CHCTR,a0 | ||
278 | movhu (a0),d2 | ||
279 | btst CHCTR_ICEN,d2 | ||
280 | beq mn10300_local_icache_inv_range_reg_end | ||
281 | |||
282 | /* calculate alignsize | ||
283 | * | ||
284 | * alignsize = L1_CACHE_BYTES; | ||
285 | * for (i = (end - start - 1) / L1_CACHE_BYTES ; i > 0; i >>= 1) { | ||
286 | * alignsize <<= 1; | ||
287 | * } | ||
288 | * d2 = alignsize; | ||
289 | */ | ||
290 | mov L1_CACHE_BYTES,d2 | ||
291 | sub d0,d1,d3 | ||
292 | add -1,d3 | ||
293 | lsr L1_CACHE_SHIFT,d3 | ||
294 | beq 2f | ||
295 | 1: | ||
296 | add d2,d2 | ||
297 | lsr 1,d3 | ||
298 | bne 1b | ||
299 | 2: | ||
300 | |||
301 | /* a1 = end */ | ||
302 | mov d1,a1 | ||
303 | |||
304 | LOCAL_CLI_SAVE(d3) | ||
305 | |||
306 | mov ICIVCR,a0 | ||
307 | /* wait for busy bit of area invalidation */ | ||
308 | setlb | ||
309 | mov (a0),d1 | ||
310 | btst ICIVCR_ICIVBSY,d1 | ||
311 | lne | ||
312 | |||
313 | /* set mask | ||
314 | * | ||
315 | * mask = ~(alignsize-1); | ||
316 | * ICIVMR = mask; | ||
317 | */ | ||
318 | mov d2,d1 | ||
319 | add -1,d1 | ||
320 | not d1 | ||
321 | mov d1,(ICIVMR) | ||
322 | /* a2 = mask & start */ | ||
323 | and d1,d0,a2 | ||
324 | |||
325 | icivloop: | ||
326 | /* area invalidate | ||
327 | * | ||
328 | * ICIVCR = (mask & start) | ICIVCR_ICI | ||
329 | */ | ||
330 | mov a2,d0 | ||
331 | or ICIVCR_ICI,d0 | ||
332 | mov d0,(a0) | ||
333 | |||
334 | /* wait for busy bit of area invalidation */ | ||
335 | setlb | ||
336 | mov (a0),d1 | ||
337 | btst ICIVCR_ICIVBSY,d1 | ||
338 | lne | ||
339 | |||
340 | /* check invalidating of end address | ||
341 | * | ||
342 | * a2 = a2 + alignsize | ||
343 | * if (a2 < end) { | ||
344 | * goto icivloop; | ||
345 | * } */ | ||
346 | add d2,a2 | ||
347 | cmp a1,a2 | ||
348 | bns icivloop | ||
349 | |||
350 | LOCAL_IRQ_RESTORE(d3) | ||
351 | |||
352 | mn10300_local_icache_inv_range_reg_end: | ||
353 | ret [d2,d3,a2],12 | ||
354 | .size mn10300_local_icache_inv_page,.-mn10300_local_icache_inv_page | ||
355 | .size mn10300_local_icache_inv_range,.-mn10300_local_icache_inv_range | ||
356 | .size mn10300_local_icache_inv_range2,.-mn10300_local_icache_inv_range2 | ||