Commit | Line | Data |
---|---|---|
0bd3eb6c | 1 | /* MN10300 CPU core caching routines, using direct tag flushing |
b920de1b DH |
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 | ||
12 | #include <linux/sys.h> | |
13 | #include <linux/linkage.h> | |
14 | #include <asm/smp.h> | |
15 | #include <asm/page.h> | |
16 | #include <asm/cache.h> | |
0bd3eb6c | 17 | #include <asm/irqflags.h> |
b920de1b DH |
18 | |
19 | .am33_2 | |
0bd3eb6c AT |
20 | |
21 | #ifndef CONFIG_SMP | |
b920de1b DH |
22 | .globl mn10300_dcache_flush |
23 | .globl mn10300_dcache_flush_page | |
24 | .globl mn10300_dcache_flush_range | |
25 | .globl mn10300_dcache_flush_range2 | |
26 | .globl mn10300_dcache_flush_inv | |
27 | .globl mn10300_dcache_flush_inv_page | |
28 | .globl mn10300_dcache_flush_inv_range | |
29 | .globl mn10300_dcache_flush_inv_range2 | |
30 | ||
0bd3eb6c AT |
31 | mn10300_dcache_flush = mn10300_local_dcache_flush |
32 | mn10300_dcache_flush_page = mn10300_local_dcache_flush_page | |
33 | mn10300_dcache_flush_range = mn10300_local_dcache_flush_range | |
34 | mn10300_dcache_flush_range2 = mn10300_local_dcache_flush_range2 | |
35 | mn10300_dcache_flush_inv = mn10300_local_dcache_flush_inv | |
36 | mn10300_dcache_flush_inv_page = mn10300_local_dcache_flush_inv_page | |
37 | mn10300_dcache_flush_inv_range = mn10300_local_dcache_flush_inv_range | |
38 | mn10300_dcache_flush_inv_range2 = mn10300_local_dcache_flush_inv_range2 | |
39 | ||
40 | #endif /* !CONFIG_SMP */ | |
41 | ||
b920de1b DH |
42 | ############################################################################### |
43 | # | |
0bd3eb6c | 44 | # void mn10300_local_dcache_flush(void) |
b920de1b DH |
45 | # Flush the entire data cache back to RAM |
46 | # | |
47 | ############################################################################### | |
48 | ALIGN | |
0bd3eb6c AT |
49 | .globl mn10300_local_dcache_flush |
50 | .type mn10300_local_dcache_flush,@function | |
51 | mn10300_local_dcache_flush: | |
b920de1b DH |
52 | movhu (CHCTR),d0 |
53 | btst CHCTR_DCEN,d0 | |
0bd3eb6c | 54 | beq mn10300_local_dcache_flush_end |
b920de1b DH |
55 | |
56 | # read the addresses tagged in the cache's tag RAM and attempt to flush | |
57 | # those addresses specifically | |
58 | # - we rely on the hardware to filter out invalid tag entry addresses | |
59 | mov DCACHE_TAG(0,0),a0 # dcache tag RAM access address | |
60 | mov DCACHE_PURGE(0,0),a1 # dcache purge request address | |
61 | mov L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1 # total number of entries | |
62 | ||
0bd3eb6c | 63 | mn10300_local_dcache_flush_loop: |
b920de1b | 64 | mov (a0),d0 |
7f386ac3 | 65 | and L1_CACHE_TAG_MASK,d0 |
b920de1b DH |
66 | or L1_CACHE_TAG_VALID,d0 # retain valid entries in the |
67 | # cache | |
68 | mov d0,(a1) # conditional purge | |
69 | ||
b920de1b DH |
70 | add L1_CACHE_BYTES,a0 |
71 | add L1_CACHE_BYTES,a1 | |
72 | add -1,d1 | |
0bd3eb6c | 73 | bne mn10300_local_dcache_flush_loop |
b920de1b | 74 | |
0bd3eb6c | 75 | mn10300_local_dcache_flush_end: |
b920de1b | 76 | ret [],0 |
0bd3eb6c | 77 | .size mn10300_local_dcache_flush,.-mn10300_local_dcache_flush |
b920de1b DH |
78 | |
79 | ############################################################################### | |
80 | # | |
0bd3eb6c AT |
81 | # void mn10300_local_dcache_flush_page(unsigned long start) |
82 | # void mn10300_local_dcache_flush_range(unsigned long start, unsigned long end) | |
83 | # void mn10300_local_dcache_flush_range2(unsigned long start, unsigned long size) | |
b920de1b DH |
84 | # Flush a range of addresses on a page in the dcache |
85 | # | |
86 | ############################################################################### | |
87 | ALIGN | |
0bd3eb6c AT |
88 | .globl mn10300_local_dcache_flush_page |
89 | .globl mn10300_local_dcache_flush_range | |
90 | .globl mn10300_local_dcache_flush_range2 | |
91 | .type mn10300_local_dcache_flush_page,@function | |
92 | .type mn10300_local_dcache_flush_range,@function | |
93 | .type mn10300_local_dcache_flush_range2,@function | |
94 | mn10300_local_dcache_flush_page: | |
95 | and ~(PAGE_SIZE-1),d0 | |
b920de1b | 96 | mov PAGE_SIZE,d1 |
0bd3eb6c | 97 | mn10300_local_dcache_flush_range2: |
b920de1b | 98 | add d0,d1 |
0bd3eb6c AT |
99 | mn10300_local_dcache_flush_range: |
100 | movm [d2],(sp) | |
b920de1b DH |
101 | |
102 | movhu (CHCTR),d2 | |
103 | btst CHCTR_DCEN,d2 | |
0bd3eb6c AT |
104 | beq mn10300_local_dcache_flush_range_end |
105 | ||
106 | sub d0,d1,a0 | |
107 | cmp MN10300_DCACHE_FLUSH_BORDER,a0 | |
108 | ble 1f | |
109 | ||
110 | movm (sp),[d2] | |
111 | bra mn10300_local_dcache_flush | |
112 | 1: | |
b920de1b DH |
113 | |
114 | # round start addr down | |
7f386ac3 | 115 | and L1_CACHE_TAG_MASK,d0 |
b920de1b DH |
116 | mov d0,a1 |
117 | ||
118 | add L1_CACHE_BYTES,d1 # round end addr up | |
7f386ac3 | 119 | and L1_CACHE_TAG_MASK,d1 |
b920de1b DH |
120 | |
121 | # write a request to flush all instances of an address from the cache | |
122 | mov DCACHE_PURGE(0,0),a0 | |
123 | mov a1,d0 | |
124 | and L1_CACHE_TAG_ENTRY,d0 | |
125 | add d0,a0 # starting dcache purge control | |
126 | # reg address | |
127 | ||
128 | sub a1,d1 | |
129 | lsr L1_CACHE_SHIFT,d1 # total number of entries to | |
130 | # examine | |
131 | ||
132 | or L1_CACHE_TAG_VALID,a1 # retain valid entries in the | |
133 | # cache | |
134 | ||
0bd3eb6c | 135 | mn10300_local_dcache_flush_range_loop: |
b920de1b DH |
136 | mov a1,(L1_CACHE_WAYDISP*0,a0) # conditionally purge this line |
137 | # all ways | |
138 | ||
139 | add L1_CACHE_BYTES,a0 | |
140 | add L1_CACHE_BYTES,a1 | |
141 | and ~L1_CACHE_WAYDISP,a0 # make sure way stay on way 0 | |
142 | add -1,d1 | |
0bd3eb6c AT |
143 | bne mn10300_local_dcache_flush_range_loop |
144 | ||
145 | mn10300_local_dcache_flush_range_end: | |
146 | ret [d2],4 | |
b920de1b | 147 | |
0bd3eb6c AT |
148 | .size mn10300_local_dcache_flush_page,.-mn10300_local_dcache_flush_page |
149 | .size mn10300_local_dcache_flush_range,.-mn10300_local_dcache_flush_range | |
150 | .size mn10300_local_dcache_flush_range2,.-mn10300_local_dcache_flush_range2 | |
b920de1b DH |
151 | |
152 | ############################################################################### | |
153 | # | |
0bd3eb6c | 154 | # void mn10300_local_dcache_flush_inv(void) |
b920de1b DH |
155 | # Flush the entire data cache and invalidate all entries |
156 | # | |
157 | ############################################################################### | |
158 | ALIGN | |
0bd3eb6c AT |
159 | .globl mn10300_local_dcache_flush_inv |
160 | .type mn10300_local_dcache_flush_inv,@function | |
161 | mn10300_local_dcache_flush_inv: | |
b920de1b DH |
162 | movhu (CHCTR),d0 |
163 | btst CHCTR_DCEN,d0 | |
0bd3eb6c | 164 | beq mn10300_local_dcache_flush_inv_end |
b920de1b | 165 | |
0bd3eb6c AT |
166 | mov L1_CACHE_NENTRIES,d1 |
167 | clr a1 | |
b920de1b | 168 | |
0bd3eb6c AT |
169 | mn10300_local_dcache_flush_inv_loop: |
170 | mov (DCACHE_PURGE_WAY0(0),a1),d0 # unconditional purge | |
171 | mov (DCACHE_PURGE_WAY1(0),a1),d0 # unconditional purge | |
172 | mov (DCACHE_PURGE_WAY2(0),a1),d0 # unconditional purge | |
173 | mov (DCACHE_PURGE_WAY3(0),a1),d0 # unconditional purge | |
b920de1b DH |
174 | |
175 | add L1_CACHE_BYTES,a1 | |
176 | add -1,d1 | |
0bd3eb6c | 177 | bne mn10300_local_dcache_flush_inv_loop |
b920de1b | 178 | |
0bd3eb6c | 179 | mn10300_local_dcache_flush_inv_end: |
b920de1b | 180 | ret [],0 |
0bd3eb6c | 181 | .size mn10300_local_dcache_flush_inv,.-mn10300_local_dcache_flush_inv |
b920de1b DH |
182 | |
183 | ############################################################################### | |
184 | # | |
0bd3eb6c AT |
185 | # void mn10300_local_dcache_flush_inv_page(unsigned long start) |
186 | # void mn10300_local_dcache_flush_inv_range(unsigned long start, unsigned long end) | |
187 | # void mn10300_local_dcache_flush_inv_range2(unsigned long start, unsigned long size) | |
b920de1b DH |
188 | # Flush and invalidate a range of addresses on a page in the dcache |
189 | # | |
190 | ############################################################################### | |
191 | ALIGN | |
0bd3eb6c AT |
192 | .globl mn10300_local_dcache_flush_inv_page |
193 | .globl mn10300_local_dcache_flush_inv_range | |
194 | .globl mn10300_local_dcache_flush_inv_range2 | |
195 | .type mn10300_local_dcache_flush_inv_page,@function | |
196 | .type mn10300_local_dcache_flush_inv_range,@function | |
197 | .type mn10300_local_dcache_flush_inv_range2,@function | |
198 | mn10300_local_dcache_flush_inv_page: | |
199 | and ~(PAGE_SIZE-1),d0 | |
b920de1b | 200 | mov PAGE_SIZE,d1 |
0bd3eb6c | 201 | mn10300_local_dcache_flush_inv_range2: |
b920de1b | 202 | add d0,d1 |
0bd3eb6c AT |
203 | mn10300_local_dcache_flush_inv_range: |
204 | movm [d2],(sp) | |
205 | ||
b920de1b DH |
206 | movhu (CHCTR),d2 |
207 | btst CHCTR_DCEN,d2 | |
0bd3eb6c AT |
208 | beq mn10300_local_dcache_flush_inv_range_end |
209 | ||
210 | sub d0,d1,a0 | |
211 | cmp MN10300_DCACHE_FLUSH_INV_BORDER,a0 | |
212 | ble 1f | |
213 | ||
214 | movm (sp),[d2] | |
215 | bra mn10300_local_dcache_flush_inv | |
216 | 1: | |
b920de1b | 217 | |
7f386ac3 | 218 | and L1_CACHE_TAG_MASK,d0 # round start addr down |
b920de1b DH |
219 | mov d0,a1 |
220 | ||
7f386ac3 DH |
221 | add L1_CACHE_BYTES,d1 # round end addr up |
222 | and L1_CACHE_TAG_MASK,d1 | |
b920de1b DH |
223 | |
224 | # write a request to flush and invalidate all instances of an address | |
225 | # from the cache | |
226 | mov DCACHE_PURGE(0,0),a0 | |
227 | mov a1,d0 | |
228 | and L1_CACHE_TAG_ENTRY,d0 | |
229 | add d0,a0 # starting dcache purge control | |
230 | # reg address | |
231 | ||
232 | sub a1,d1 | |
233 | lsr L1_CACHE_SHIFT,d1 # total number of entries to | |
234 | # examine | |
235 | ||
0bd3eb6c | 236 | mn10300_local_dcache_flush_inv_range_loop: |
b920de1b DH |
237 | mov a1,(L1_CACHE_WAYDISP*0,a0) # conditionally purge this line |
238 | # in all ways | |
239 | ||
240 | add L1_CACHE_BYTES,a0 | |
241 | add L1_CACHE_BYTES,a1 | |
242 | and ~L1_CACHE_WAYDISP,a0 # make sure way stay on way 0 | |
243 | add -1,d1 | |
0bd3eb6c | 244 | bne mn10300_local_dcache_flush_inv_range_loop |
b920de1b | 245 | |
0bd3eb6c AT |
246 | mn10300_local_dcache_flush_inv_range_end: |
247 | ret [d2],4 | |
248 | .size mn10300_local_dcache_flush_inv_page,.-mn10300_local_dcache_flush_inv_page | |
249 | .size mn10300_local_dcache_flush_inv_range,.-mn10300_local_dcache_flush_inv_range | |
250 | .size mn10300_local_dcache_flush_inv_range2,.-mn10300_local_dcache_flush_inv_range2 |