1 /* $NetBSD: cache_tx39.c,v 1.8 2016/07/11 16:15:36 matt Exp $ */
2
3 /*
4 * Copyright 2001 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: cache_tx39.c,v 1.8 2016/07/11 16:15:36 matt Exp $");
40
41 #include <sys/param.h>
42
43 #include <mips/cache.h>
44 #include <mips/cache_tx39.h>
45 #include <mips/locore.h>
46
47 /*
48 * Cache operations for TX3900/TX3920-style caches:
49 *
50 * - I-cache direct-mapped (TX3900) or 2-way set-associative (TX3920)
51 * - D-cache 2-way set-associative
52 * - Write-through (TX3900, TX3920) or write-back (TX3920)
53 * - Physically indexed, phyiscally tagged
54 *
55 * XXX THIS IS NOT YET COMPLETE.
56 */
57
58 #define round_line(x) (((x) + 15) & ~15)
59 #define trunc_line(x) ((x) & ~15)
60
61 void
tx3900_icache_sync_all_16(void)62 tx3900_icache_sync_all_16(void)
63 {
64
65 tx3900_icache_do_inv_index_16(MIPS_PHYS_TO_KSEG0(0),
66 MIPS_PHYS_TO_KSEG0(mips_cache_info.mci_picache_size));
67 }
68
69 void
tx3900_icache_sync_range_16(register_t va,vsize_t size)70 tx3900_icache_sync_range_16(register_t va, vsize_t size)
71 {
72 vaddr_t eva = round_line(va + size);
73
74 va = trunc_line(va);
75
76 if ((eva - va) >= mips_cache_info.mci_picache_size) {
77 /* Just hit the whole thing. */
78 va = MIPS_PHYS_TO_KSEG0(0);
79 eva = MIPS_PHYS_TO_KSEG0(mips_cache_info.mci_picache_size);
80 }
81
82 tx3900_icache_do_inv_index_16(va, eva);
83 }
84
85 #undef round_line
86 #undef trunc_line
87
88 #define round_line(x) (((x) + 3) & ~3)
89 #define trunc_line(x) ((x) & ~3)
90
91 static int tx3900_dummy_buffer[R3900_C_SIZE_MAX / sizeof(int)];
92
93 void
tx3900_pdcache_wbinv_all_4(void)94 tx3900_pdcache_wbinv_all_4(void)
95 {
96 vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
97 vaddr_t eva = va + mips_cache_info.mci_pdcache_size;
98 volatile int *p;
99
100 /*
101 * No Index Invalidate for the TX3900 -- have to execute a
102 * series of load instructions from the dummy buffer, instead.
103 */
104
105 p = tx3900_dummy_buffer;
106 while (va < eva) {
107 (void) *p++; (void) *p++; (void) *p++; (void) *p++;
108 (void) *p++; (void) *p++; (void) *p++; (void) *p++;
109 (void) *p++; (void) *p++; (void) *p++; (void) *p++;
110 (void) *p++; (void) *p++; (void) *p++; (void) *p++;
111 (void) *p++; (void) *p++; (void) *p++; (void) *p++;
112 (void) *p++; (void) *p++; (void) *p++; (void) *p++;
113 (void) *p++; (void) *p++; (void) *p++; (void) *p++;
114 (void) *p++; (void) *p++; (void) *p++; (void) *p++;
115 va += (32 * 4);
116 }
117 }
118
119 void
tx3900_pdcache_inv_range_4(register_t va,vsize_t size)120 tx3900_pdcache_inv_range_4(register_t va, vsize_t size)
121 {
122 vaddr_t eva = round_line(va + size);
123
124 va = trunc_line(va);
125
126 while ((eva - va) >= (32 * 4)) {
127 cache_tx39_op_32lines_4(va,
128 CACHE_TX39_D|CACHEOP_TX3900_HIT_INV);
129 va += (32 * 4);
130 };
131
132 while (va < eva) {
133 cache_op_tx39_line(va, CACHE_TX39_D|CACHEOP_TX3900_HIT_INV);
134 va += 4;
135 }
136 }
137
138 void
tx3900_pdcache_wb_range_4(register_t va,vsize_t size)139 tx3900_pdcache_wb_range_4(register_t va, vsize_t size)
140 {
141
142 /* Cache is write-through. */
143 }
144
145 #undef round_line
146 #undef trunc_line
147
148 #define round_line(x) (((x) + 15) & ~15)
149 #define trunc_line(x) ((x) & ~15)
150
151 void
tx3920_icache_sync_all_16wb(void)152 tx3920_icache_sync_all_16wb(void)
153 {
154
155 mips_dcache_wbinv_all();
156
157 __asm volatile(".set push; .set mips2; sync; .set pop");
158
159 tx3920_icache_do_inv_16(MIPS_PHYS_TO_KSEG0(0),
160 MIPS_PHYS_TO_KSEG0(mips_cache_info.mci_picache_size));
161 }
162
163 void
tx3920_icache_sync_range_16wt(register_t va,vsize_t size)164 tx3920_icache_sync_range_16wt(register_t va, vsize_t size)
165 {
166 vaddr_t eva = round_line(va + size);
167
168 va = trunc_line(va);
169
170 tx3920_icache_do_inv_16(va, eva);
171 }
172
173 void
tx3920_icache_sync_range_16wb(register_t va,vsize_t size)174 tx3920_icache_sync_range_16wb(register_t va, vsize_t size)
175 {
176 vaddr_t eva = round_line(va + size);
177
178 va = trunc_line(va);
179
180 mips_dcache_wb_range(va, (eva - va));
181
182 __asm volatile(".set push; .set mips2; sync; .set pop");
183
184 tx3920_icache_do_inv_16(va, eva);
185 }
186
187 void
tx3920_pdcache_wbinv_all_16wt(void)188 tx3920_pdcache_wbinv_all_16wt(void)
189 {
190 vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
191 vaddr_t eva = va + mips_cache_info.mci_pdcache_size;
192
193 /*
194 * Since we're hitting the whole thing, we don't have to
195 * worry about the 2 different "ways".
196 */
197
198 while (va < eva) {
199 cache_tx39_op_32lines_16(va,
200 CACHE_TX39_D|CACHEOP_TX3920_INDEX_INV);
201 va += (32 * 16);
202 }
203 }
204
205 void
tx3920_pdcache_wbinv_all_16wb(void)206 tx3920_pdcache_wbinv_all_16wb(void)
207 {
208 vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
209 vaddr_t eva = va + mips_cache_info.mci_pdcache_size;
210
211 /*
212 * Since we're hitting the whole thing, we don't have to
213 * worry about the 2 different "ways".
214 */
215
216 while (va < eva) {
217 cache_tx39_op_32lines_16(va,
218 CACHE_TX39_D|CACHEOP_TX3920_INDEX_WB_INV);
219 va += (32 * 16);
220 }
221 }
222
223 void
tx3920_pdcache_wbinv_range_16wb(register_t va,vsize_t size)224 tx3920_pdcache_wbinv_range_16wb(register_t va, vsize_t size)
225 {
226 vaddr_t eva = round_line(va + size);
227
228 va = trunc_line(va);
229
230 while ((eva - va) >= (32 * 16)) {
231 cache_tx39_op_32lines_16(va,
232 CACHE_TX39_D|CACHEOP_TX3920_HIT_WB_INV);
233 va += (32 * 16);
234 }
235
236 while (va < eva) {
237 cache_op_tx39_line(va, CACHE_TX39_D|CACHEOP_TX3920_HIT_WB_INV);
238 va += 16;
239 }
240 }
241
242 void
tx3920_pdcache_inv_range_16(register_t va,vsize_t size)243 tx3920_pdcache_inv_range_16(register_t va, vsize_t size)
244 {
245 vaddr_t eva = round_line(va + size);
246
247 va = trunc_line(va);
248
249 while ((eva - va) >= (32 * 16)) {
250 cache_tx39_op_32lines_16(va,
251 CACHE_TX39_D|CACHEOP_TX3920_HIT_INV);
252 va += (32 * 16);
253 }
254
255 while (va < eva) {
256 cache_op_tx39_line(va, CACHE_TX39_D|CACHEOP_TX3920_HIT_INV);
257 va += 16;
258 }
259 }
260
261 void
tx3920_pdcache_wb_range_16wt(register_t va,vsize_t size)262 tx3920_pdcache_wb_range_16wt(register_t va, vsize_t size)
263 {
264
265 /* Cache is write-through. */
266 }
267
268 void
tx3920_pdcache_wb_range_16wb(register_t va,vsize_t size)269 tx3920_pdcache_wb_range_16wb(register_t va, vsize_t size)
270 {
271 vaddr_t eva = round_line(va + size);
272
273 va = trunc_line(va);
274
275 while ((eva - va) >= (32 * 16)) {
276 cache_tx39_op_32lines_16(va,
277 CACHE_TX39_D|CACHEOP_TX3920_HIT_WB);
278 va += (32 * 16);
279 }
280
281 while (va < eva) {
282 cache_op_tx39_line(va, CACHE_TX39_D|CACHEOP_TX3920_HIT_WB);
283 va += 16;
284 }
285 }
286