1 /* MN10300 CPU core caching routines, using indirect regs on cache controller
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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.
12 #include <linux/sys.h>
13 #include <linux/linkage.h>
16 #include <asm/cache.h>
17 #include <asm/irqflags.h>
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
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
40 #endif /* !CONFIG_SMP */
42 ###############################################################################
44 # void mn10300_local_dcache_flush(void)
45 # Flush the entire data cache back to RAM
47 ###############################################################################
49 .globl mn10300_local_dcache_flush
50 .type mn10300_local_dcache_flush,@function
51 mn10300_local_dcache_flush:
54 beq mn10300_local_dcache_flush_end
60 # wait for busy bit of area purge
63 btst DCPGCR_DCPGBSY,d0
77 # wait for busy bit of area purge
80 btst DCPGCR_DCPGBSY,d0
85 mn10300_local_dcache_flush_end:
87 .size mn10300_local_dcache_flush,.-mn10300_local_dcache_flush
89 ###############################################################################
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
96 ###############################################################################
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
107 mn10300_local_dcache_flush_range2:
109 mn10300_local_dcache_flush_range:
114 beq mn10300_local_dcache_flush_range_end
116 # calculate alignsize
118 # alignsize = L1_CACHE_BYTES;
119 # for (i = (end - start - 1) / L1_CACHE_BYTES ; i > 0; i >>= 1)
123 mov L1_CACHE_BYTES,d2
126 lsr L1_CACHE_SHIFT,d3
138 # wait for busy bit of area purge
141 btst DCPGCR_DCPGBSY,d1
147 not d1 # d1 = mask = ~(alignsize-1)
150 and d1,d0,a2 # a2 = mask & start
156 mov d0,(a0) # DCPGCR = (mask & start) | DCPGCR_DCP
158 # wait for busy bit of area purge
161 btst DCPGCR_DCPGBSY,d1
164 # check purge of end address
165 add d2,a2 # a2 += alignsize
166 cmp a1,a2 # if (a2 < end) goto dcpgloop
169 LOCAL_IRQ_RESTORE(d3)
171 mn10300_local_dcache_flush_range_end:
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
178 ###############################################################################
180 # void mn10300_local_dcache_flush_inv(void)
181 # Flush the entire data cache and invalidate all entries
183 ###############################################################################
185 .globl mn10300_local_dcache_flush_inv
186 .type mn10300_local_dcache_flush_inv,@function
187 mn10300_local_dcache_flush_inv:
190 beq mn10300_local_dcache_flush_inv_end
196 # wait for busy bit of area purge & invalidate
199 btst DCPGCR_DCPGBSY,d0
202 # set the mask to cover everything
206 # area purge & invalidate
207 mov DCPGCR_DCP|DCPGCR_DCI,d0
210 # wait for busy bit of area purge & invalidate
213 btst DCPGCR_DCPGBSY,d0
216 LOCAL_IRQ_RESTORE(d1)
218 mn10300_local_dcache_flush_inv_end:
220 .size mn10300_local_dcache_flush_inv,.-mn10300_local_dcache_flush_inv
222 ###############################################################################
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
229 ###############################################################################
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
240 mn10300_local_dcache_flush_inv_range2:
242 mn10300_local_dcache_flush_inv_range:
247 beq mn10300_local_dcache_flush_inv_range_end
249 # calculate alignsize
251 # alignsize = L1_CACHE_BYTES;
252 # for (i = (end - start - 1) / L1_CACHE_BYTES; i > 0; i >>= 1)
256 mov L1_CACHE_BYTES,d2
259 lsr L1_CACHE_SHIFT,d3
271 # wait for busy bit of area purge & invalidate
274 btst DCPGCR_DCPGBSY,d1
280 not d1 # d1 = mask = ~(alignsize-1)
283 and d1,d0,a2 # a2 = mask & start
286 # area purge & invalidate
288 or DCPGCR_DCP|DCPGCR_DCI,d0
289 mov d0,(a0) # DCPGCR = (mask & start)|DCPGCR_DCP|DCPGCR_DCI
291 # wait for busy bit of area purge & invalidate
294 btst DCPGCR_DCPGBSY,d1
297 # check purge & invalidate of end address
298 add d2,a2 # a2 += alignsize
299 cmp a1,a2 # if (a2 < end) goto dcpgivloop
302 LOCAL_IRQ_RESTORE(d3)
304 mn10300_local_dcache_flush_inv_range_end:
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