]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - arch/mn10300/mm/cache-inv-by-tag.S
Merge remote-tracking branch 'asoc/fix/core' into tmp
[mirror_ubuntu-bionic-kernel.git] / arch / mn10300 / mm / cache-inv-by-tag.S
1 /* 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>
16 #include <asm/irqflags.h>
17 #include <asm/cacheflush.h>
18 #include "cache.inc"
19
20 #define mn10300_local_dcache_inv_range_intr_interval \
21 +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
22
23 #if mn10300_local_dcache_inv_range_intr_interval > 0xff
24 #error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less
25 #endif
26
27 .am33_2
28
29 .globl mn10300_local_icache_inv_page
30 .globl mn10300_local_icache_inv_range
31 .globl mn10300_local_icache_inv_range2
32
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
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
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
55
56 #endif /* !CONFIG_SMP */
57
58 ###############################################################################
59 #
60 # void mn10300_local_icache_inv(void)
61 # Invalidate the entire icache
62 #
63 ###############################################################################
64 ALIGN
65 .globl mn10300_local_icache_inv
66 .type mn10300_local_icache_inv,@function
67 mn10300_local_icache_inv:
68 mov CHCTR,a0
69
70 movhu (a0),d0
71 btst CHCTR_ICEN,d0
72 beq mn10300_local_icache_inv_end
73
74 invalidate_icache 1
75
76 mn10300_local_icache_inv_end:
77 ret [],0
78 .size mn10300_local_icache_inv,.-mn10300_local_icache_inv
79
80 ###############################################################################
81 #
82 # void mn10300_local_dcache_inv(void)
83 # Invalidate the entire dcache
84 #
85 ###############################################################################
86 ALIGN
87 .globl mn10300_local_dcache_inv
88 .type mn10300_local_dcache_inv,@function
89 mn10300_local_dcache_inv:
90 mov CHCTR,a0
91
92 movhu (a0),d0
93 btst CHCTR_DCEN,d0
94 beq mn10300_local_dcache_inv_end
95
96 invalidate_dcache 1
97
98 mn10300_local_dcache_inv_end:
99 ret [],0
100 .size mn10300_local_dcache_inv,.-mn10300_local_dcache_inv
101
102 ###############################################################################
103 #
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
108 #
109 ###############################################################################
110 ALIGN
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
119 mov PAGE_SIZE,d1
120 mn10300_local_dcache_inv_range2:
121 add d0,d1
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
128 bne 1f
129 btst ~L1_CACHE_TAG_MASK,d1
130 beq 2f
131 1:
132 bra mn10300_local_dcache_flush_inv_range
133 2:
134 #endif /* CONFIG_MN10300_CACHE_WBACK */
135
136 movm [d2,d3,a2],(sp)
137
138 mov CHCTR,a2
139 movhu (a2),d2
140 btst CHCTR_DCEN,d2
141 beq mn10300_local_dcache_inv_range_end
142
143 #ifndef CONFIG_MN10300_CACHE_WBACK
144 and L1_CACHE_TAG_MASK,d0 # round start addr down
145
146 add L1_CACHE_BYTES,d1 # round end addr up
147 and L1_CACHE_TAG_MASK,d1
148 #endif /* !CONFIG_MN10300_CACHE_WBACK */
149 mov d0,a1
150
151 clr d2 # we're going to clear tag RAM
152 # 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
168 mn10300_local_dcache_inv_range_outer_loop:
169 LOCAL_CLI_SAVE(d3)
170
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
182 mn10300_local_dcache_inv_range_loop:
183
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
188 # is not valid
189
190 xor a1,d0
191 lsr 12,d0
192 bne mn10300_local_dcache_inv_range_skip_0 # jump if not this cacheline
193
194 mov d2,(L1_CACHE_WAYDISP*0,a0) # kill the tag
195
196 mn10300_local_dcache_inv_range_skip_0:
197
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
202 # is not valid
203
204 xor a1,d0
205 lsr 12,d0
206 bne mn10300_local_dcache_inv_range_skip_1 # jump if not this cacheline
207
208 mov d2,(L1_CACHE_WAYDISP*1,a0) # kill the tag
209
210 mn10300_local_dcache_inv_range_skip_1:
211
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
216 # is not valid
217
218 xor a1,d0
219 lsr 12,d0
220 bne mn10300_local_dcache_inv_range_skip_2 # jump if not this cacheline
221
222 mov d2,(L1_CACHE_WAYDISP*2,a0) # kill the tag
223
224 mn10300_local_dcache_inv_range_skip_2:
225
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
230 # is not valid
231
232 xor a1,d0
233 lsr 12,d0
234 bne mn10300_local_dcache_inv_range_skip_3 # jump if not this cacheline
235
236 mov d2,(L1_CACHE_WAYDISP*3,a0) # kill the tag
237
238 mn10300_local_dcache_inv_range_skip_3:
239
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
247 add -1,d1
248 btst mn10300_local_dcache_inv_range_intr_interval,d1
249 bne mn10300_local_dcache_inv_range_loop
250
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
266 LOCAL_IRQ_RESTORE(d3)
267
268 # go around again if the counter hasn't yet reached zero
269 add 0,d1
270 bne mn10300_local_dcache_inv_range_outer_loop
271
272 mn10300_local_dcache_inv_range_end:
273 ret [d2,d3,a2],12
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