blob: ccedce9c144d30459b8d092959247d4713ee03f0 [file] [log] [blame]
David Howellsb920de12008-02-08 04:19:31 -08001/* MN10300 CPU core caching routines
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>
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +010016#include <asm/irqflags.h>
17#include <asm/cacheflush.h>
David Howellsb75bb232011-03-18 16:54:29 +000018#include "cache.inc"
David Howellsb920de12008-02-08 04:19:31 -080019
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +010020#define mn10300_local_dcache_inv_range_intr_interval \
David Howellsb920de12008-02-08 04:19:31 -080021 +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
22
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +010023#if mn10300_local_dcache_inv_range_intr_interval > 0xff
David Howellsb920de12008-02-08 04:19:31 -080024#error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less
25#endif
26
27 .am33_2
28
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +010029 .globl mn10300_local_icache_inv_page
30 .globl mn10300_local_icache_inv_range
31 .globl mn10300_local_icache_inv_range2
32
33mn10300_local_icache_inv_page = mn10300_local_icache_inv
34mn10300_local_icache_inv_range = mn10300_local_icache_inv
35mn10300_local_icache_inv_range2 = mn10300_local_icache_inv
36
37#ifndef CONFIG_SMP
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
46
47mn10300_icache_inv = mn10300_local_icache_inv
48mn10300_icache_inv_page = mn10300_local_icache_inv_page
49mn10300_icache_inv_range = mn10300_local_icache_inv_range
50mn10300_icache_inv_range2 = mn10300_local_icache_inv_range2
51mn10300_dcache_inv = mn10300_local_dcache_inv
52mn10300_dcache_inv_page = mn10300_local_dcache_inv_page
53mn10300_dcache_inv_range = mn10300_local_dcache_inv_range
54mn10300_dcache_inv_range2 = mn10300_local_dcache_inv_range2
55
56#endif /* !CONFIG_SMP */
David Howellsb920de12008-02-08 04:19:31 -080057
58###############################################################################
59#
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +010060# void mn10300_local_icache_inv(void)
David Howellsb920de12008-02-08 04:19:31 -080061# Invalidate the entire icache
62#
63###############################################################################
64 ALIGN
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +010065 .globl mn10300_local_icache_inv
66 .type mn10300_local_icache_inv,@function
67mn10300_local_icache_inv:
David Howellsb920de12008-02-08 04:19:31 -080068 mov CHCTR,a0
69
70 movhu (a0),d0
71 btst CHCTR_ICEN,d0
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +010072 beq mn10300_local_icache_inv_end
David Howellsb920de12008-02-08 04:19:31 -080073
David Howellsb75bb232011-03-18 16:54:29 +000074 invalidate_icache 1
David Howellsb920de12008-02-08 04:19:31 -080075
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +010076mn10300_local_icache_inv_end:
David Howellsb920de12008-02-08 04:19:31 -080077 ret [],0
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +010078 .size mn10300_local_icache_inv,.-mn10300_local_icache_inv
David Howellsb920de12008-02-08 04:19:31 -080079
80###############################################################################
81#
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +010082# void mn10300_local_dcache_inv(void)
David Howellsb920de12008-02-08 04:19:31 -080083# Invalidate the entire dcache
84#
85###############################################################################
86 ALIGN
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +010087 .globl mn10300_local_dcache_inv
88 .type mn10300_local_dcache_inv,@function
89mn10300_local_dcache_inv:
David Howellsb920de12008-02-08 04:19:31 -080090 mov CHCTR,a0
91
92 movhu (a0),d0
93 btst CHCTR_DCEN,d0
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +010094 beq mn10300_local_dcache_inv_end
David Howellsb920de12008-02-08 04:19:31 -080095
David Howellsb75bb232011-03-18 16:54:29 +000096 invalidate_dcache 1
David Howellsb920de12008-02-08 04:19:31 -080097
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +010098mn10300_local_dcache_inv_end:
David Howellsb920de12008-02-08 04:19:31 -080099 ret [],0
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100100 .size mn10300_local_dcache_inv,.-mn10300_local_dcache_inv
David Howellsb920de12008-02-08 04:19:31 -0800101
102###############################################################################
103#
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100104# 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)
David Howellsb920de12008-02-08 04:19:31 -0800107# Invalidate a range of addresses on a page in the dcache
108#
109###############################################################################
110 ALIGN
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100111 .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
117mn10300_local_dcache_inv_page:
118 and ~(PAGE_SIZE-1),d0
David Howellsb920de12008-02-08 04:19:31 -0800119 mov PAGE_SIZE,d1
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100120mn10300_local_dcache_inv_range2:
David Howellsb920de12008-02-08 04:19:31 -0800121 add d0,d1
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100122mn10300_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
David Howells7f386ac2011-03-18 16:54:30 +0000127 btst ~L1_CACHE_TAG_MASK,d0
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100128 bne 1f
David Howells7f386ac2011-03-18 16:54:30 +0000129 btst ~L1_CACHE_TAG_MASK,d1
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100130 beq 2f
1311:
132 bra mn10300_local_dcache_flush_inv_range
1332:
134#endif /* CONFIG_MN10300_CACHE_WBACK */
David Howellsb920de12008-02-08 04:19:31 -0800135
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100136 movm [d2,d3,a2],(sp)
137
138 mov CHCTR,a2
David Howellsb920de12008-02-08 04:19:31 -0800139 movhu (a2),d2
140 btst CHCTR_DCEN,d2
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100141 beq mn10300_local_dcache_inv_range_end
David Howellsb920de12008-02-08 04:19:31 -0800142
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100143#ifndef CONFIG_MN10300_CACHE_WBACK
David Howells7f386ac2011-03-18 16:54:30 +0000144 and L1_CACHE_TAG_MASK,d0 # round start addr down
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100145
146 add L1_CACHE_BYTES,d1 # round end addr up
David Howells7f386ac2011-03-18 16:54:30 +0000147 and L1_CACHE_TAG_MASK,d1
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100148#endif /* !CONFIG_MN10300_CACHE_WBACK */
David Howellsb920de12008-02-08 04:19:31 -0800149 mov d0,a1
150
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100151 clr d2 # we're going to clear tag RAM
David Howellsb920de12008-02-08 04:19:31 -0800152 # entries
153
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
157 mov a1,d0
158 and L1_CACHE_TAG_ENTRY,d0
159 add d0,a0 # starting dcache tag RAM
160 # access address
161
162 sub a1,d1
163 lsr L1_CACHE_SHIFT,d1 # total number of entries to
164 # examine
165
166 and ~(L1_CACHE_DISPARITY-1),a1 # determine comparator base
167
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100168mn10300_local_dcache_inv_range_outer_loop:
169 LOCAL_CLI_SAVE(d3)
David Howellsb920de12008-02-08 04:19:31 -0800170
171 # disable the dcache
172 movhu (a2),d0
173 and ~CHCTR_DCEN,d0
174 movhu d0,(a2)
175
176 # and wait for it to calm down
177 setlb
178 movhu (a2),d0
179 btst CHCTR_DCBUSY,d0
180 lne
181
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100182mn10300_local_dcache_inv_range_loop:
David Howellsb920de12008-02-08 04:19:31 -0800183
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
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100187 beq mn10300_local_dcache_inv_range_skip_0 # jump if this cacheline
188 # is not valid
David Howellsb920de12008-02-08 04:19:31 -0800189
190 xor a1,d0
191 lsr 12,d0
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100192 bne mn10300_local_dcache_inv_range_skip_0 # jump if not this cacheline
David Howellsb920de12008-02-08 04:19:31 -0800193
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100194 mov d2,(L1_CACHE_WAYDISP*0,a0) # kill the tag
David Howellsb920de12008-02-08 04:19:31 -0800195
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100196mn10300_local_dcache_inv_range_skip_0:
David Howellsb920de12008-02-08 04:19:31 -0800197
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
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100201 beq mn10300_local_dcache_inv_range_skip_1 # jump if this cacheline
202 # is not valid
David Howellsb920de12008-02-08 04:19:31 -0800203
204 xor a1,d0
205 lsr 12,d0
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100206 bne mn10300_local_dcache_inv_range_skip_1 # jump if not this cacheline
David Howellsb920de12008-02-08 04:19:31 -0800207
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100208 mov d2,(L1_CACHE_WAYDISP*1,a0) # kill the tag
David Howellsb920de12008-02-08 04:19:31 -0800209
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100210mn10300_local_dcache_inv_range_skip_1:
David Howellsb920de12008-02-08 04:19:31 -0800211
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
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100215 beq mn10300_local_dcache_inv_range_skip_2 # jump if this cacheline
216 # is not valid
David Howellsb920de12008-02-08 04:19:31 -0800217
218 xor a1,d0
219 lsr 12,d0
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100220 bne mn10300_local_dcache_inv_range_skip_2 # jump if not this cacheline
David Howellsb920de12008-02-08 04:19:31 -0800221
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100222 mov d2,(L1_CACHE_WAYDISP*2,a0) # kill the tag
David Howellsb920de12008-02-08 04:19:31 -0800223
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100224mn10300_local_dcache_inv_range_skip_2:
David Howellsb920de12008-02-08 04:19:31 -0800225
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
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100229 beq mn10300_local_dcache_inv_range_skip_3 # jump if this cacheline
230 # is not valid
David Howellsb920de12008-02-08 04:19:31 -0800231
232 xor a1,d0
233 lsr 12,d0
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100234 bne mn10300_local_dcache_inv_range_skip_3 # jump if not this cacheline
David Howellsb920de12008-02-08 04:19:31 -0800235
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100236 mov d2,(L1_CACHE_WAYDISP*3,a0) # kill the tag
David Howellsb920de12008-02-08 04:19:31 -0800237
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100238mn10300_local_dcache_inv_range_skip_3:
David Howellsb920de12008-02-08 04:19:31 -0800239
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
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100246 and ~L1_CACHE_WAYDISP,a0
David Howellsb920de12008-02-08 04:19:31 -0800247 add -1,d1
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100248 btst mn10300_local_dcache_inv_range_intr_interval,d1
249 bne mn10300_local_dcache_inv_range_loop
David Howellsb920de12008-02-08 04:19:31 -0800250
251 # wait for the cache to finish what it's doing
252 setlb
253 movhu (a2),d0
254 btst CHCTR_DCBUSY,d0
255 lne
256
257 # and reenable it
258 or CHCTR_DCEN,d0
259 movhu d0,(a2)
260 movhu (a2),d0
261
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
265 # to happen
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100266 LOCAL_IRQ_RESTORE(d3)
David Howellsb920de12008-02-08 04:19:31 -0800267
268 # go around again if the counter hasn't yet reached zero
269 add 0,d1
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100270 bne mn10300_local_dcache_inv_range_outer_loop
David Howellsb920de12008-02-08 04:19:31 -0800271
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100272mn10300_local_dcache_inv_range_end:
David Howellsb920de12008-02-08 04:19:31 -0800273 ret [d2,d3,a2],12
Akira Takeuchi0bd3eb62010-10-27 17:28:45 +0100274 .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