1 /* MN10300 CPU cache invalidation routines, using automatic purge registers
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
30 .globl mn10300_icache_inv
31 .globl mn10300_icache_inv_page
32 .globl mn10300_icache_inv_range
33 .globl mn10300_icache_inv_range2
34 .globl mn10300_dcache_inv
35 .globl mn10300_dcache_inv_page
36 .globl mn10300_dcache_inv_range
37 .globl mn10300_dcache_inv_range2
39 mn10300_icache_inv = mn10300_local_icache_inv
40 mn10300_icache_inv_page = mn10300_local_icache_inv_page
41 mn10300_icache_inv_range = mn10300_local_icache_inv_range
42 mn10300_icache_inv_range2 = mn10300_local_icache_inv_range2
43 mn10300_dcache_inv = mn10300_local_dcache_inv
44 mn10300_dcache_inv_page = mn10300_local_dcache_inv_page
45 mn10300_dcache_inv_range = mn10300_local_dcache_inv_range
46 mn10300_dcache_inv_range2 = mn10300_local_dcache_inv_range2
48 #endif /* !CONFIG_SMP */
50 ###############################################################################
52 # void mn10300_local_icache_inv(void)
53 # Invalidate the entire icache
55 ###############################################################################
57 .globl mn10300_local_icache_inv
58 .type mn10300_local_icache_inv,@function
59 mn10300_local_icache_inv:
64 beq mn10300_local_icache_inv_end
68 mn10300_local_icache_inv_end:
70 .size mn10300_local_icache_inv,.-mn10300_local_icache_inv
72 ###############################################################################
74 # void mn10300_local_dcache_inv(void)
75 # Invalidate the entire dcache
77 ###############################################################################
79 .globl mn10300_local_dcache_inv
80 .type mn10300_local_dcache_inv,@function
81 mn10300_local_dcache_inv:
86 beq mn10300_local_dcache_inv_end
90 mn10300_local_dcache_inv_end:
92 .size mn10300_local_dcache_inv,.-mn10300_local_dcache_inv
94 ###############################################################################
96 # void mn10300_local_dcache_inv_range(unsigned long start, unsigned long end)
97 # void mn10300_local_dcache_inv_range2(unsigned long start, unsigned long size)
98 # void mn10300_local_dcache_inv_page(unsigned long start)
99 # Invalidate a range of addresses on a page in the dcache
101 ###############################################################################
103 .globl mn10300_local_dcache_inv_page
104 .globl mn10300_local_dcache_inv_range
105 .globl mn10300_local_dcache_inv_range2
106 .type mn10300_local_dcache_inv_page,@function
107 .type mn10300_local_dcache_inv_range,@function
108 .type mn10300_local_dcache_inv_range2,@function
109 mn10300_local_dcache_inv_page:
110 and ~(PAGE_SIZE-1),d0
112 mn10300_local_dcache_inv_range2:
114 mn10300_local_dcache_inv_range:
115 # If we are in writeback mode we check the start and end alignments,
116 # and if they're not cacheline-aligned, we must flush any bits outside
117 # the range that share cachelines with stuff inside the range
118 #ifdef CONFIG_MN10300_CACHE_WBACK
119 btst ~L1_CACHE_TAG_MASK,d0
121 btst ~L1_CACHE_TAG_MASK,d1
124 bra mn10300_local_dcache_flush_inv_range
126 #endif /* CONFIG_MN10300_CACHE_WBACK */
133 beq mn10300_local_dcache_inv_range_end
135 # round the addresses out to be full cachelines, unless we're in
136 # writeback mode, in which case we would be in flush and invalidate by
138 #ifndef CONFIG_MN10300_CACHE_WBACK
139 and L1_CACHE_TAG_MASK,d0 # round start addr down
141 mov L1_CACHE_BYTES-1,d2
143 and L1_CACHE_TAG_MASK,d1 # round end addr up
144 #endif /* !CONFIG_MN10300_CACHE_WBACK */
146 sub d0,d1,d2 # calculate the total size
147 mov d0,a2 # A2 = start address
148 mov d1,a1 # A1 = end address
152 mov DCPGCR,a0 # make sure the purger isn't busy
155 btst DCPGCR_DCPGBSY,d0
158 # skip initial address alignment calculation if address is zero
164 /* calculate alignsize
166 * alignsize = L1_CACHE_BYTES;
167 * while (! start & alignsize) {
172 mov L1_CACHE_BYTES,d1
183 * if (totalsize > alignsize) {
184 * invsize = alignsize;
186 * invsize = totalsize;
188 * while (! invsize & tmp) {
199 mov 0x80000000,d0 # start from 31bit=1
210 * mask = ~(invsize-1);
221 mov d0,(a0) # DCPGCR = (mask & start) | DCPGCR_DCI
223 setlb # wait for the purge to complete
225 btst DCPGCR_DCPGBSY,d0
228 sub d1,d2 # decrease size remaining
229 add d1,a2 # increase next start address
231 /* check invalidating of end address
240 LOCAL_IRQ_RESTORE(d3)
242 mn10300_local_dcache_inv_range_end:
244 .size mn10300_local_dcache_inv_page,.-mn10300_local_dcache_inv_page
245 .size mn10300_local_dcache_inv_range,.-mn10300_local_dcache_inv_range
246 .size mn10300_local_dcache_inv_range2,.-mn10300_local_dcache_inv_range2
248 ###############################################################################
250 # void mn10300_local_icache_inv_page(unsigned long start)
251 # void mn10300_local_icache_inv_range2(unsigned long start, unsigned long size)
252 # void mn10300_local_icache_inv_range(unsigned long start, unsigned long end)
253 # Invalidate a range of addresses on a page in the icache
255 ###############################################################################
257 .globl mn10300_local_icache_inv_page
258 .globl mn10300_local_icache_inv_range
259 .globl mn10300_local_icache_inv_range2
260 .type mn10300_local_icache_inv_page,@function
261 .type mn10300_local_icache_inv_range,@function
262 .type mn10300_local_icache_inv_range2,@function
263 mn10300_local_icache_inv_page:
264 and ~(PAGE_SIZE-1),d0
266 mn10300_local_icache_inv_range2:
268 mn10300_local_icache_inv_range:
274 beq mn10300_local_icache_inv_range_reg_end
276 /* calculate alignsize
278 * alignsize = L1_CACHE_BYTES;
279 * for (i = (end - start - 1) / L1_CACHE_BYTES ; i > 0; i >>= 1) {
284 mov L1_CACHE_BYTES,d2
287 lsr L1_CACHE_SHIFT,d3
301 /* wait for busy bit of area invalidation */
304 btst ICIVCR_ICIVBSY,d1
309 * mask = ~(alignsize-1);
316 /* a2 = mask & start */
322 * ICIVCR = (mask & start) | ICIVCR_ICI
328 /* wait for busy bit of area invalidation */
331 btst ICIVCR_ICIVBSY,d1
334 /* check invalidating of end address
336 * a2 = a2 + alignsize
344 LOCAL_IRQ_RESTORE(d3)
346 mn10300_local_icache_inv_range_reg_end:
348 .size mn10300_local_icache_inv_page,.-mn10300_local_icache_inv_page
349 .size mn10300_local_icache_inv_range,.-mn10300_local_icache_inv_range
350 .size mn10300_local_icache_inv_range2,.-mn10300_local_icache_inv_range2