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