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