1 /* MN10300 CPU core caching routines
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.
11 #include <linux/sys.h>
12 #include <linux/linkage.h>
15 #include <asm/cache.h>
16 #include <asm/irqflags.h>
17 #include <asm/cacheflush.h>
19 #define mn10300_local_dcache_inv_range_intr_interval \
20 +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
22 #if mn10300_local_dcache_inv_range_intr_interval > 0xff
23 #error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less
28 .globl mn10300_local_icache_inv_page
29 .globl mn10300_local_icache_inv_range
30 .globl mn10300_local_icache_inv_range2
32 mn10300_local_icache_inv_page = mn10300_local_icache_inv
33 mn10300_local_icache_inv_range = mn10300_local_icache_inv
34 mn10300_local_icache_inv_range2 = mn10300_local_icache_inv
37 .globl mn10300_icache_inv
38 .globl mn10300_icache_inv_page
39 .globl mn10300_icache_inv_range
40 .globl mn10300_icache_inv_range2
41 .globl mn10300_dcache_inv
42 .globl mn10300_dcache_inv_page
43 .globl mn10300_dcache_inv_range
44 .globl mn10300_dcache_inv_range2
46 mn10300_icache_inv = mn10300_local_icache_inv
47 mn10300_icache_inv_page = mn10300_local_icache_inv_page
48 mn10300_icache_inv_range = mn10300_local_icache_inv_range
49 mn10300_icache_inv_range2 = mn10300_local_icache_inv_range2
50 mn10300_dcache_inv = mn10300_local_dcache_inv
51 mn10300_dcache_inv_page = mn10300_local_dcache_inv_page
52 mn10300_dcache_inv_range = mn10300_local_dcache_inv_range
53 mn10300_dcache_inv_range2 = mn10300_local_dcache_inv_range2
55 #endif /* !CONFIG_SMP */
57 ###############################################################################
59 # void mn10300_local_icache_inv(void)
60 # Invalidate the entire icache
62 ###############################################################################
64 .globl mn10300_local_icache_inv
65 .type mn10300_local_icache_inv,@function
66 mn10300_local_icache_inv:
71 beq mn10300_local_icache_inv_end
73 #if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
80 # and wait for it to calm down
90 # wait for the cache to finish
103 LOCAL_IRQ_RESTORE(d1)
104 #else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
109 #endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
111 mn10300_local_icache_inv_end:
113 .size mn10300_local_icache_inv,.-mn10300_local_icache_inv
115 ###############################################################################
117 # void mn10300_local_dcache_inv(void)
118 # Invalidate the entire dcache
120 ###############################################################################
122 .globl mn10300_local_dcache_inv
123 .type mn10300_local_dcache_inv,@function
124 mn10300_local_dcache_inv:
129 beq mn10300_local_dcache_inv_end
131 #if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
138 # and wait for it to calm down
148 # wait for the cache to finish
161 LOCAL_IRQ_RESTORE(d1)
162 #else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
167 #endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
169 mn10300_local_dcache_inv_end:
171 .size mn10300_local_dcache_inv,.-mn10300_local_dcache_inv
173 ###############################################################################
175 # void mn10300_local_dcache_inv_range(unsigned long start, unsigned long end)
176 # void mn10300_local_dcache_inv_range2(unsigned long start, unsigned long size)
177 # void mn10300_local_dcache_inv_page(unsigned long start)
178 # Invalidate a range of addresses on a page in the dcache
180 ###############################################################################
182 .globl mn10300_local_dcache_inv_page
183 .globl mn10300_local_dcache_inv_range
184 .globl mn10300_local_dcache_inv_range2
185 .type mn10300_local_dcache_inv_page,@function
186 .type mn10300_local_dcache_inv_range,@function
187 .type mn10300_local_dcache_inv_range2,@function
188 mn10300_local_dcache_inv_page:
189 and ~(PAGE_SIZE-1),d0
191 mn10300_local_dcache_inv_range2:
193 mn10300_local_dcache_inv_range:
194 # If we are in writeback mode we check the start and end alignments,
195 # and if they're not cacheline-aligned, we must flush any bits outside
196 # the range that share cachelines with stuff inside the range
197 #ifdef CONFIG_MN10300_CACHE_WBACK
198 btst ~(L1_CACHE_BYTES-1),d0
200 btst ~(L1_CACHE_BYTES-1),d1
203 bra mn10300_local_dcache_flush_inv_range
205 #endif /* CONFIG_MN10300_CACHE_WBACK */
212 beq mn10300_local_dcache_inv_range_end
214 #ifndef CONFIG_MN10300_CACHE_WBACK
215 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 # round start
218 add L1_CACHE_BYTES,d1 # round end addr up
219 and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
220 #endif /* !CONFIG_MN10300_CACHE_WBACK */
223 clr d2 # we're going to clear tag RAM
226 # read the tags from the tag RAM, and if they indicate a valid dirty
227 # cache line then invalidate that line
228 mov DCACHE_TAG(0,0),a0
230 and L1_CACHE_TAG_ENTRY,d0
231 add d0,a0 # starting dcache tag RAM
235 lsr L1_CACHE_SHIFT,d1 # total number of entries to
238 and ~(L1_CACHE_DISPARITY-1),a1 # determine comparator base
240 mn10300_local_dcache_inv_range_outer_loop:
248 # and wait for it to calm down
254 mn10300_local_dcache_inv_range_loop:
256 # process the way 0 slot
257 mov (L1_CACHE_WAYDISP*0,a0),d0 # read the tag in the way 0 slot
258 btst L1_CACHE_TAG_VALID,d0
259 beq mn10300_local_dcache_inv_range_skip_0 # jump if this cacheline
264 bne mn10300_local_dcache_inv_range_skip_0 # jump if not this cacheline
266 mov d2,(L1_CACHE_WAYDISP*0,a0) # kill the tag
268 mn10300_local_dcache_inv_range_skip_0:
270 # process the way 1 slot
271 mov (L1_CACHE_WAYDISP*1,a0),d0 # read the tag in the way 1 slot
272 btst L1_CACHE_TAG_VALID,d0
273 beq mn10300_local_dcache_inv_range_skip_1 # jump if this cacheline
278 bne mn10300_local_dcache_inv_range_skip_1 # jump if not this cacheline
280 mov d2,(L1_CACHE_WAYDISP*1,a0) # kill the tag
282 mn10300_local_dcache_inv_range_skip_1:
284 # process the way 2 slot
285 mov (L1_CACHE_WAYDISP*2,a0),d0 # read the tag in the way 2 slot
286 btst L1_CACHE_TAG_VALID,d0
287 beq mn10300_local_dcache_inv_range_skip_2 # jump if this cacheline
292 bne mn10300_local_dcache_inv_range_skip_2 # jump if not this cacheline
294 mov d2,(L1_CACHE_WAYDISP*2,a0) # kill the tag
296 mn10300_local_dcache_inv_range_skip_2:
298 # process the way 3 slot
299 mov (L1_CACHE_WAYDISP*3,a0),d0 # read the tag in the way 3 slot
300 btst L1_CACHE_TAG_VALID,d0
301 beq mn10300_local_dcache_inv_range_skip_3 # jump if this cacheline
306 bne mn10300_local_dcache_inv_range_skip_3 # jump if not this cacheline
308 mov d2,(L1_CACHE_WAYDISP*3,a0) # kill the tag
310 mn10300_local_dcache_inv_range_skip_3:
312 # approx every N steps we re-enable the cache and see if there are any
313 # interrupts to be processed
314 # we also break out if we've reached the end of the loop
315 # (the bottom nibble of the count is zero in both cases)
316 add L1_CACHE_BYTES,a0
317 add L1_CACHE_BYTES,a1
318 and ~L1_CACHE_WAYDISP,a0
320 btst mn10300_local_dcache_inv_range_intr_interval,d1
321 bne mn10300_local_dcache_inv_range_loop
323 # wait for the cache to finish what it's doing
334 # re-enable interrupts
335 # - we don't bother with delay NOPs as we'll have enough instructions
336 # before we disable interrupts again to give the interrupts a chance
338 LOCAL_IRQ_RESTORE(d3)
340 # go around again if the counter hasn't yet reached zero
342 bne mn10300_local_dcache_inv_range_outer_loop
344 mn10300_local_dcache_inv_range_end:
346 .size mn10300_local_dcache_inv_page,.-mn10300_local_dcache_inv_page
347 .size mn10300_local_dcache_inv_range,.-mn10300_local_dcache_inv_range
348 .size mn10300_local_dcache_inv_range2,.-mn10300_local_dcache_inv_range2