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>
20 #define mn10300_local_dcache_inv_range_intr_interval \
21 +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
23 #if mn10300_local_dcache_inv_range_intr_interval > 0xff
24 #error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less
29 .globl mn10300_local_icache_inv_page
30 .globl mn10300_local_icache_inv_range
31 .globl mn10300_local_icache_inv_range2
33 mn10300_local_icache_inv_page = mn10300_local_icache_inv
34 mn10300_local_icache_inv_range = mn10300_local_icache_inv
35 mn10300_local_icache_inv_range2 = mn10300_local_icache_inv
38 .globl mn10300_icache_inv
39 .globl mn10300_icache_inv_page
40 .globl mn10300_icache_inv_range
41 .globl mn10300_icache_inv_range2
42 .globl mn10300_dcache_inv
43 .globl mn10300_dcache_inv_page
44 .globl mn10300_dcache_inv_range
45 .globl mn10300_dcache_inv_range2
47 mn10300_icache_inv = mn10300_local_icache_inv
48 mn10300_icache_inv_page = mn10300_local_icache_inv_page
49 mn10300_icache_inv_range = mn10300_local_icache_inv_range
50 mn10300_icache_inv_range2 = mn10300_local_icache_inv_range2
51 mn10300_dcache_inv = mn10300_local_dcache_inv
52 mn10300_dcache_inv_page = mn10300_local_dcache_inv_page
53 mn10300_dcache_inv_range = mn10300_local_dcache_inv_range
54 mn10300_dcache_inv_range2 = mn10300_local_dcache_inv_range2
56 #endif /* !CONFIG_SMP */
58 ###############################################################################
60 # void mn10300_local_icache_inv(void)
61 # Invalidate the entire icache
63 ###############################################################################
65 .globl mn10300_local_icache_inv
66 .type mn10300_local_icache_inv,@function
67 mn10300_local_icache_inv:
72 beq mn10300_local_icache_inv_end
76 mn10300_local_icache_inv_end:
78 .size mn10300_local_icache_inv,.-mn10300_local_icache_inv
80 ###############################################################################
82 # void mn10300_local_dcache_inv(void)
83 # Invalidate the entire dcache
85 ###############################################################################
87 .globl mn10300_local_dcache_inv
88 .type mn10300_local_dcache_inv,@function
89 mn10300_local_dcache_inv:
94 beq mn10300_local_dcache_inv_end
98 mn10300_local_dcache_inv_end:
100 .size mn10300_local_dcache_inv,.-mn10300_local_dcache_inv
102 ###############################################################################
104 # void mn10300_local_dcache_inv_range(unsigned long start, unsigned long end)
105 # void mn10300_local_dcache_inv_range2(unsigned long start, unsigned long size)
106 # void mn10300_local_dcache_inv_page(unsigned long start)
107 # Invalidate a range of addresses on a page in the dcache
109 ###############################################################################
111 .globl mn10300_local_dcache_inv_page
112 .globl mn10300_local_dcache_inv_range
113 .globl mn10300_local_dcache_inv_range2
114 .type mn10300_local_dcache_inv_page,@function
115 .type mn10300_local_dcache_inv_range,@function
116 .type mn10300_local_dcache_inv_range2,@function
117 mn10300_local_dcache_inv_page:
118 and ~(PAGE_SIZE-1),d0
120 mn10300_local_dcache_inv_range2:
122 mn10300_local_dcache_inv_range:
123 # If we are in writeback mode we check the start and end alignments,
124 # and if they're not cacheline-aligned, we must flush any bits outside
125 # the range that share cachelines with stuff inside the range
126 #ifdef CONFIG_MN10300_CACHE_WBACK
127 btst ~L1_CACHE_TAG_MASK,d0
129 btst ~L1_CACHE_TAG_MASK,d1
132 bra mn10300_local_dcache_flush_inv_range
134 #endif /* CONFIG_MN10300_CACHE_WBACK */
141 beq mn10300_local_dcache_inv_range_end
143 #ifndef CONFIG_MN10300_CACHE_WBACK
144 and L1_CACHE_TAG_MASK,d0 # round start addr down
146 add L1_CACHE_BYTES,d1 # round end addr up
147 and L1_CACHE_TAG_MASK,d1
148 #endif /* !CONFIG_MN10300_CACHE_WBACK */
151 clr d2 # we're going to clear tag RAM
154 # read the tags from the tag RAM, and if they indicate a valid dirty
155 # cache line then invalidate that line
156 mov DCACHE_TAG(0,0),a0
158 and L1_CACHE_TAG_ENTRY,d0
159 add d0,a0 # starting dcache tag RAM
163 lsr L1_CACHE_SHIFT,d1 # total number of entries to
166 and ~(L1_CACHE_DISPARITY-1),a1 # determine comparator base
168 mn10300_local_dcache_inv_range_outer_loop:
176 # and wait for it to calm down
182 mn10300_local_dcache_inv_range_loop:
184 # process the way 0 slot
185 mov (L1_CACHE_WAYDISP*0,a0),d0 # read the tag in the way 0 slot
186 btst L1_CACHE_TAG_VALID,d0
187 beq mn10300_local_dcache_inv_range_skip_0 # jump if this cacheline
192 bne mn10300_local_dcache_inv_range_skip_0 # jump if not this cacheline
194 mov d2,(L1_CACHE_WAYDISP*0,a0) # kill the tag
196 mn10300_local_dcache_inv_range_skip_0:
198 # process the way 1 slot
199 mov (L1_CACHE_WAYDISP*1,a0),d0 # read the tag in the way 1 slot
200 btst L1_CACHE_TAG_VALID,d0
201 beq mn10300_local_dcache_inv_range_skip_1 # jump if this cacheline
206 bne mn10300_local_dcache_inv_range_skip_1 # jump if not this cacheline
208 mov d2,(L1_CACHE_WAYDISP*1,a0) # kill the tag
210 mn10300_local_dcache_inv_range_skip_1:
212 # process the way 2 slot
213 mov (L1_CACHE_WAYDISP*2,a0),d0 # read the tag in the way 2 slot
214 btst L1_CACHE_TAG_VALID,d0
215 beq mn10300_local_dcache_inv_range_skip_2 # jump if this cacheline
220 bne mn10300_local_dcache_inv_range_skip_2 # jump if not this cacheline
222 mov d2,(L1_CACHE_WAYDISP*2,a0) # kill the tag
224 mn10300_local_dcache_inv_range_skip_2:
226 # process the way 3 slot
227 mov (L1_CACHE_WAYDISP*3,a0),d0 # read the tag in the way 3 slot
228 btst L1_CACHE_TAG_VALID,d0
229 beq mn10300_local_dcache_inv_range_skip_3 # jump if this cacheline
234 bne mn10300_local_dcache_inv_range_skip_3 # jump if not this cacheline
236 mov d2,(L1_CACHE_WAYDISP*3,a0) # kill the tag
238 mn10300_local_dcache_inv_range_skip_3:
240 # approx every N steps we re-enable the cache and see if there are any
241 # interrupts to be processed
242 # we also break out if we've reached the end of the loop
243 # (the bottom nibble of the count is zero in both cases)
244 add L1_CACHE_BYTES,a0
245 add L1_CACHE_BYTES,a1
246 and ~L1_CACHE_WAYDISP,a0
248 btst mn10300_local_dcache_inv_range_intr_interval,d1
249 bne mn10300_local_dcache_inv_range_loop
251 # wait for the cache to finish what it's doing
262 # re-enable interrupts
263 # - we don't bother with delay NOPs as we'll have enough instructions
264 # before we disable interrupts again to give the interrupts a chance
266 LOCAL_IRQ_RESTORE(d3)
268 # go around again if the counter hasn't yet reached zero
270 bne mn10300_local_dcache_inv_range_outer_loop
272 mn10300_local_dcache_inv_range_end:
274 .size mn10300_local_dcache_inv_page,.-mn10300_local_dcache_inv_page
275 .size mn10300_local_dcache_inv_range,.-mn10300_local_dcache_inv_range
276 .size mn10300_local_dcache_inv_range2,.-mn10300_local_dcache_inv_range2