xref: /netbsd/sys/arch/mips/mips/cache_r10k.c (revision 6550d01e)
1 /*	$NetBSD: cache_r10k.c,v 1.4 2005/12/24 20:07:19 perry Exp $	*/
2 
3 /*-
4  * Copyright (c) 2003 Takao Shinohara.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 /*
28  * Copyright 2001 Wasabi Systems, Inc.
29  * All rights reserved.
30  *
31  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
32  *
33  * Redistribution and use in source and binary forms, with or without
34  * modification, are permitted provided that the following conditions
35  * are met:
36  * 1. Redistributions of source code must retain the above copyright
37  *    notice, this list of conditions and the following disclaimer.
38  * 2. Redistributions in binary form must reproduce the above copyright
39  *    notice, this list of conditions and the following disclaimer in the
40  *    documentation and/or other materials provided with the distribution.
41  * 3. All advertising materials mentioning features or use of this software
42  *    must display the following acknowledgement:
43  *	This product includes software developed for the NetBSD Project by
44  *	Wasabi Systems, Inc.
45  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
46  *    or promote products derived from this software without specific prior
47  *    written permission.
48  *
49  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
51  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
52  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
53  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
54  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
55  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
56  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
57  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
58  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
59  * POSSIBILITY OF SUCH DAMAGE.
60  */
61 
62 #include <sys/param.h>
63 
64 #include <mips/cache.h>
65 #include <mips/cache_r4k.h>
66 #include <mips/cache_r10k.h>
67 
68 /*
69  * Cache operations for R10000-style caches:
70  *
71  *	2-way, write-back
72  *	primary cache: virtual index/physical tag
73  *	secondary cache: physical index/physical tag
74  */
75 
76 __asm(".set mips3");
77 
78 #define	round_line(x)	(((x) + 64 - 1) & ~(64 - 1))
79 #define	trunc_line(x)	((x) & ~(64 - 1))
80 
81 void
82 r10k_icache_sync_all(void)
83 {
84 	vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
85 	vaddr_t eva = va + mips_picache_way_size;
86 
87 	mips_dcache_wbinv_all();
88 
89 	__asm volatile("sync");
90 
91 	while (va < eva) {
92 		cache_op_r4k_line(va+0, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
93 		cache_op_r4k_line(va+1, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
94 		va += 64;
95 	}
96 }
97 
98 void
99 r10k_icache_sync_range(vaddr_t va, vsize_t size)
100 {
101 	vaddr_t eva = round_line(va + size);
102 
103 	va = trunc_line(va);
104 
105 	mips_dcache_wb_range(va, (eva - va));
106 
107 	__asm volatile("sync");
108 
109 	while (va < eva) {
110 		cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
111 		va += 64;
112 	}
113 }
114 
115 void
116 r10k_icache_sync_range_index(vaddr_t va, vsize_t size)
117 {
118 	vaddr_t eva, orig_va;
119 
120 	orig_va = va;
121 
122 	eva = round_line(va + size);
123 	va = trunc_line(va);
124 
125 	mips_dcache_wbinv_range_index(va, (eva - va));
126 
127 	__asm volatile("sync");
128 
129 	/*
130 	 * Since we're doing Index ops, we expect to not be able
131 	 * to access the address we've been given.  So, get the
132 	 * bits that determine the cache index, and make a KSEG0
133 	 * address out of them.
134 	 */
135 	va = MIPS_PHYS_TO_KSEG0(orig_va & mips_picache_way_mask);
136 
137 	eva = round_line(va + size);
138 	va = trunc_line(va);
139 
140 	while (va < eva) {
141 		cache_op_r4k_line(va+0, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
142 		cache_op_r4k_line(va+1, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
143 		va += 64;
144 	}
145 }
146 
147 #undef round_line
148 #undef trunc_line
149 
150 #define	round_line(x)	(((x) + 32 - 1) & ~(32 - 1))
151 #define	trunc_line(x)	((x) & ~(32 - 1))
152 
153 void
154 r10k_pdcache_wbinv_all(void)
155 {
156 	vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
157 	vaddr_t eva = va + mips_pdcache_way_size;
158 
159 	while (va < eva) {
160 		cache_op_r4k_line(va+0, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
161 		cache_op_r4k_line(va+1, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
162 		va += 32;
163 	}
164 }
165 
166 void
167 r10k_pdcache_wbinv_range(vaddr_t va, vsize_t size)
168 {
169 	vaddr_t eva = round_line(va + size);
170 
171 	va = trunc_line(va);
172 
173 	while (va < eva) {
174 		cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
175 		va += 32;
176 	}
177 }
178 
179 void
180 r10k_pdcache_wbinv_range_index(vaddr_t va, vsize_t size)
181 {
182 	vaddr_t eva;
183 
184 	/*
185 	 * Since we're doing Index ops, we expect to not be able
186 	 * to access the address we've been given.  So, get the
187 	 * bits that determine the cache index, and make a KSEG0
188 	 * address out of them.
189 	 */
190 	va = MIPS_PHYS_TO_KSEG0(va & mips_pdcache_way_mask);
191 
192 	eva = round_line(va + size);
193 	va = trunc_line(va);
194 
195 	while (va < eva) {
196 		cache_op_r4k_line(va+0, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
197 		cache_op_r4k_line(va+1, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
198 		va += 32;
199 	}
200 }
201 
202 void
203 r10k_pdcache_inv_range(vaddr_t va, vsize_t size)
204 {
205 	vaddr_t eva = round_line(va + size);
206 
207 	va = trunc_line(va);
208 
209 	while (va < eva) {
210 		cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
211 		va += 32;
212 	}
213 }
214 
215 void
216 r10k_pdcache_wb_range(vaddr_t va, vsize_t size)
217 {
218 	vaddr_t eva = round_line(va + size);
219 
220 	va = trunc_line(va);
221 
222 	while (va < eva) {
223 		/* R10000 does not support HitWriteBack operation */
224 		cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
225 		va += 32;
226 	}
227 }
228 
229 #undef round_line
230 #undef trunc_line
231 
232 #define	round_line(x)	(((x) + mips_sdcache_line_size - 1) & ~(mips_sdcache_line_size - 1))
233 #define	trunc_line(x)	((x) & ~(mips_sdcache_line_size - 1))
234 
235 void
236 r10k_sdcache_wbinv_all(void)
237 {
238 	vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
239 	vaddr_t eva = va + mips_sdcache_way_size;
240 	int line_size = mips_sdcache_line_size;
241 
242 	while (va < eva) {
243 		cache_op_r4k_line(va+0, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
244 		cache_op_r4k_line(va+1, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
245 		va += line_size;
246 	}
247 }
248 
249 void
250 r10k_sdcache_wbinv_range(vaddr_t va, vsize_t size)
251 {
252 	vaddr_t eva = round_line(va + size);
253 	int line_size = mips_sdcache_line_size;
254 
255 	va = trunc_line(va);
256 
257 	while (va < eva) {
258 		cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
259 		va += line_size;
260 	}
261 }
262 
263 void
264 r10k_sdcache_wbinv_range_index(vaddr_t va, vsize_t size)
265 {
266 	vaddr_t eva;
267 	int line_size = mips_sdcache_line_size;
268 
269 	/*
270 	 * Since we're doing Index ops, we expect to not be able
271 	 * to access the address we've been given.  So, get the
272 	 * bits that determine the cache index, and make a KSEG0
273 	 * address out of them.
274 	 */
275 	va = MIPS_PHYS_TO_KSEG0(va & mips_sdcache_way_mask);
276 
277 	eva = round_line(va + size);
278 	va = trunc_line(va);
279 
280 	while (va < eva) {
281 		cache_op_r4k_line(va+0, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
282 		cache_op_r4k_line(va+1, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
283 		va += line_size;
284 	}
285 }
286 
287 void
288 r10k_sdcache_inv_range(vaddr_t va, vsize_t size)
289 {
290 	vaddr_t eva = round_line(va + size);
291 	int line_size = mips_sdcache_line_size;
292 
293 	va = trunc_line(va);
294 
295 	while (va < eva) {
296 		cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
297 		va += line_size;
298 	}
299 }
300 
301 void
302 r10k_sdcache_wb_range(vaddr_t va, vsize_t size)
303 {
304 	vaddr_t eva = round_line(va + size);
305 	int line_size = mips_sdcache_line_size;
306 
307 	va = trunc_line(va);
308 
309 	while (va < eva) {
310 		/* R10000 does not support HitWriteBack operation */
311 		cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
312 		va += line_size;
313 	}
314 }
315 
316 #undef round_line
317 #undef trunc_line
318