xref: /netbsd-src/sys/arch/arm/arm/cpufunc.c (revision 3b01aba77a7a698587faaae455bbfe740923c1f5)
1 /*	$NetBSD: cpufunc.c,v 1.11 2001/07/09 19:51:14 reinoud Exp $	*/
2 
3 /*
4  * arm7tdmi support code Copyright (c) 2001 John Fremlin
5  * arm8 support code Copyright (c) 1997 ARM Limited
6  * arm8 support code Copyright (c) 1997 Causality Limited
7  * Copyright (c) 1997 Mark Brinicombe.
8  * Copyright (c) 1997 Causality Limited
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by Causality Limited.
22  * 4. The name of Causality Limited may not be used to endorse or promote
23  *    products derived from this software without specific prior written
24  *    permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
27  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29  * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
30  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  * RiscBSD kernel project
39  *
40  * cpufuncs.c
41  *
42  * C functions for supporting CPU / MMU / TLB specific operations.
43  *
44  * Created      : 30/01/97
45  */
46 
47 #include "opt_compat_netbsd.h"
48 #include "opt_cputypes.h"
49 #include "opt_pmap_debug.h"
50 
51 #include <sys/types.h>
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <machine/cpu.h>
55 #include <machine/cpufunc.h>
56 #include <machine/bootconfig.h>
57 #include <arch/arm/arm/disassem.h>
58 
59 #ifdef CPU_ARM3
60 struct cpu_functions arm3_cpufuncs = {
61 	/* CPU functions */
62 
63 	cpufunc_id,			/* id			 */
64 
65 	/* MMU functions */
66 
67 	arm3_control,			/* control		*/
68 	NULL,				/* domain		*/
69 	NULL,				/* setttb		*/
70 	NULL,				/* faultstatus		*/
71 	NULL,				/* faultaddress		*/
72 
73 	/* TLB functions */
74 
75 	cpufunc_nullop,			/* tlb_flushID		*/
76 	(void *)cpufunc_nullop,		/* tlb_flushID_SE	*/
77 	cpufunc_nullop,			/* tlb_flushI		*/
78 	(void *)cpufunc_nullop,		/* tlb_flushI_SE	*/
79 	cpufunc_nullop,			/* tlb_flushD		*/
80 	(void *)cpufunc_nullop,		/* tlb_flushD_SE	*/
81 
82 	/* Cache functions */
83 
84 	arm3_cache_flush,		/* cache_flushID	*/
85 	(void *)arm3_cache_flush,	/* cache_flushID_SE	*/
86 	arm3_cache_flush,		/* cache_flushI		*/
87 	(void *)arm3_cache_flush,	/* cache_flushI_SE	*/
88 	arm3_cache_flush,		/* cache_flushD		*/
89 	(void *)arm3_cache_flush,	/* cache_flushD_SE	*/
90 
91 	cpufunc_nullop,			/* cache_cleanID	s*/
92 	(void *)cpufunc_nullop,		/* cache_cleanID_E	s*/
93 	cpufunc_nullop,			/* cache_cleanD		s*/
94 	(void *)cpufunc_nullop,		/* cache_cleanD_E	*/
95 
96 	arm3_cache_flush,		/* cache_purgeID	s*/
97 	(void *)arm3_cache_flush,	/* cache_purgeID_E	s*/
98 	arm3_cache_flush,		/* cache_purgeD		s*/
99 	(void *)arm3_cache_flush,	/* cache_purgeD_E	s*/
100 
101 	/* Other functions */
102 
103 	cpufunc_nullop,			/* flush_prefetchbuf	*/
104 	cpufunc_nullop,			/* drain_writebuf	*/
105 	cpufunc_nullop,			/* flush_brnchtgt_C	*/
106 	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
107 
108 	(void *)cpufunc_nullop,		/* sleep		*/
109 
110 	/* Soft functions */
111 
112 	cpufunc_nullop,			/* cache_syncI		*/
113 	(void *)cpufunc_nullop,		/* cache_cleanID_rng	*/
114 	(void *)cpufunc_nullop,		/* cache_cleanD_rng	*/
115 	(void *)arm3_cache_flush,	/* cache_purgeID_rng	*/
116 	(void *)arm3_cache_flush,	/* cache_purgeD_rng	*/
117 	(void *)cpufunc_nullop,		/* cache_syncI_rng	*/
118 
119 	early_abort_fixup,		/* dataabt_fixup	*/
120 	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
121 
122 	NULL,				/* context_switch	*/
123 
124 	(void *)cpufunc_nullop		/* cpu setup		*/
125 
126 };
127 #endif	/* CPU_ARM3 */
128 
129 #ifdef CPU_ARM6
130 struct cpu_functions arm6_cpufuncs = {
131 	/* CPU functions */
132 
133 	cpufunc_id,			/* id			 */
134 
135 	/* MMU functions */
136 
137 	cpufunc_control,		/* control		*/
138 	cpufunc_domains,		/* domain		*/
139 	arm67_setttb,			/* setttb		*/
140 	cpufunc_faultstatus,		/* faultstatus		*/
141 	cpufunc_faultaddress,		/* faultaddress		*/
142 
143 	/* TLB functions */
144 
145 	arm67_tlb_flush,		/* tlb_flushID		*/
146 	arm67_tlb_purge,		/* tlb_flushID_SE	*/
147 	arm67_tlb_flush,		/* tlb_flushI		*/
148 	arm67_tlb_purge,		/* tlb_flushI_SE	*/
149 	arm67_tlb_flush,		/* tlb_flushD		*/
150 	arm67_tlb_purge,		/* tlb_flushD_SE	*/
151 
152 	/* Cache functions */
153 
154 	arm67_cache_flush,		/* cache_flushID	*/
155 	(void *)arm67_cache_flush,	/* cache_flushID_SE	*/
156 	arm67_cache_flush,		/* cache_flushI		*/
157 	(void *)arm67_cache_flush,	/* cache_flushI_SE	*/
158 	arm67_cache_flush,		/* cache_flushD		*/
159 	(void *)arm67_cache_flush,	/* cache_flushD_SE	*/
160 
161 	cpufunc_nullop,			/* cache_cleanID	s*/
162 	(void *)cpufunc_nullop,		/* cache_cleanID_E	s*/
163 	cpufunc_nullop,			/* cache_cleanD		s*/
164 	(void *)cpufunc_nullop,		/* cache_cleanD_E	*/
165 
166 	arm67_cache_flush,		/* cache_purgeID	s*/
167 	(void *)arm67_cache_flush,	/* cache_purgeID_E	s*/
168 	arm67_cache_flush,		/* cache_purgeD		s*/
169 	(void *)arm67_cache_flush,	/* cache_purgeD_E	s*/
170 
171 	/* Other functions */
172 
173 	cpufunc_nullop,			/* flush_prefetchbuf	*/
174 	cpufunc_nullop,			/* drain_writebuf	*/
175 	cpufunc_nullop,			/* flush_brnchtgt_C	*/
176 	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
177 
178 	(void *)cpufunc_nullop,		/* sleep		*/
179 
180 	/* Soft functions */
181 
182 	cpufunc_nullop,			/* cache_syncI		*/
183 	(void *)cpufunc_nullop,		/* cache_cleanID_rng	*/
184 	(void *)cpufunc_nullop,		/* cache_cleanD_rng	*/
185 	(void *)arm67_cache_flush,	/* cache_purgeID_rng	*/
186 	(void *)arm67_cache_flush,	/* cache_purgeD_rng	*/
187 	(void *)cpufunc_nullop,		/* cache_syncI_rng	*/
188 
189 #ifdef ARM6_LATE_ABORT
190 	late_abort_fixup,		/* dataabt_fixup	*/
191 #else
192 	early_abort_fixup,		/* dataabt_fixup	*/
193 #endif
194 	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
195 
196 	arm67_context_switch,		/* context_switch	*/
197 
198 	arm6_setup			/* cpu setup		*/
199 
200 };
201 #endif	/* CPU_ARM6 */
202 
203 #ifdef CPU_ARM7
204 struct cpu_functions arm7_cpufuncs = {
205 	/* CPU functions */
206 
207 	cpufunc_id,			/* id			 */
208 
209 	/* MMU functions */
210 
211 	cpufunc_control,		/* control		*/
212 	cpufunc_domains,		/* domain		*/
213 	arm67_setttb,			/* setttb		*/
214 	cpufunc_faultstatus,		/* faultstatus		*/
215 	cpufunc_faultaddress,		/* faultaddress		*/
216 
217 	/* TLB functions */
218 
219 	arm67_tlb_flush,		/* tlb_flushID		*/
220 	arm67_tlb_purge,		/* tlb_flushID_SE	*/
221 	arm67_tlb_flush,		/* tlb_flushI		*/
222 	arm67_tlb_purge,		/* tlb_flushI_SE	*/
223 	arm67_tlb_flush,		/* tlb_flushD		*/
224 	arm67_tlb_purge,		/* tlb_flushD_SE	*/
225 
226 	/* Cache functions */
227 
228 	arm67_cache_flush,		/* cache_flushID	*/
229 	(void *)arm67_cache_flush,	/* cache_flushID_SE	*/
230 	arm67_cache_flush,		/* cache_flushI		*/
231 	(void *)arm67_cache_flush,	/* cache_flushI_SE	*/
232 	arm67_cache_flush,		/* cache_flushD		*/
233 	(void *)arm67_cache_flush,	/* cache_flushD_SE	*/
234 
235 	cpufunc_nullop,			/* cache_cleanID	s*/
236 	(void *)cpufunc_nullop,		/* cache_cleanID_E	s*/
237 	cpufunc_nullop,			/* cache_cleanD		s*/
238 	(void *)cpufunc_nullop,		/* cache_cleanD_E	*/
239 
240 	arm67_cache_flush,		/* cache_purgeID	s*/
241 	(void *)arm67_cache_flush,	/* cache_purgeID_E	s*/
242 	arm67_cache_flush,		/* cache_purgeD		s*/
243 	(void *)arm67_cache_flush,	/* cache_purgeD_E	s*/
244 
245 	/* Other functions */
246 
247 	cpufunc_nullop,			/* flush_prefetchbuf	*/
248 	cpufunc_nullop,			/* drain_writebuf	*/
249 	cpufunc_nullop,			/* flush_brnchtgt_C	*/
250 	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
251 
252 	(void *)cpufunc_nullop,		/* sleep		*/
253 
254 	/* Soft functions */
255 
256 	cpufunc_nullop,			/* cache_syncI		*/
257 	(void *)cpufunc_nullop,		/* cache_cleanID_rng	*/
258 	(void *)cpufunc_nullop,		/* cache_cleanD_rng	*/
259 	(void *)arm67_cache_flush,	/* cache_purgeID_rng	*/
260 	(void *)arm67_cache_flush,	/* cache_purgeD_rng	*/
261 	(void *)cpufunc_nullop,		/* cache_syncI_rng	*/
262 
263 	late_abort_fixup,		/* dataabt_fixup	*/
264 	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
265 
266 	arm67_context_switch,		/* context_switch	*/
267 
268 	arm7_setup			/* cpu setup		*/
269 
270 };
271 #endif	/* CPU_ARM7 */
272 
273 #ifdef CPU_ARM7TDMI
274 struct cpu_functions arm7tdmi_cpufuncs = {
275 	/* CPU functions */
276 
277 	cpufunc_id,			/* id			 */
278 
279 	/* MMU functions */
280 
281 	cpufunc_control,		/* control		*/
282 	cpufunc_domains,		/* domain		*/
283 	arm7tdmi_setttb,			/* setttb		*/
284 	cpufunc_faultstatus,		/* faultstatus		*/
285 	cpufunc_faultaddress,		/* faultaddress		*/
286 
287 	/* TLB functions */
288 
289 	arm7tdmi_tlb_flushID,		/* tlb_flushID		*/
290 	arm7tdmi_tlb_flushID_SE,		/* tlb_flushID_SE	*/
291 	arm7tdmi_tlb_flushID,		/* tlb_flushI		*/
292 	arm7tdmi_tlb_flushID_SE,		/* tlb_flushI_SE	*/
293 	arm7tdmi_tlb_flushID,		/* tlb_flushD		*/
294 	arm7tdmi_tlb_flushID_SE,		/* tlb_flushD_SE	*/
295 
296 	/* Cache functions */
297 
298 	arm7tdmi_cache_flushID,		/* cache_flushID	*/
299 	(void *)arm7tdmi_cache_flushID,	/* cache_flushID_SE	*/
300 	arm7tdmi_cache_flushID,		/* cache_flushI		*/
301 	(void *)arm7tdmi_cache_flushID,	/* cache_flushI_SE	*/
302 	arm7tdmi_cache_flushID,		/* cache_flushD		*/
303 	(void *)arm7tdmi_cache_flushID,	/* cache_flushD_SE	*/
304 
305 	cpufunc_nullop,			/* cache_cleanID	s*/
306 	(void *)cpufunc_nullop,		/* cache_cleanID_E	s*/
307 	cpufunc_nullop,			/* cache_cleanD		s*/
308 	(void *)cpufunc_nullop,		/* cache_cleanD_E	*/
309 
310 	arm7tdmi_cache_flushID,		/* cache_purgeID	s*/
311 	(void *)arm7tdmi_cache_flushID,	/* cache_purgeID_E	s*/
312 	arm7tdmi_cache_flushID,		/* cache_purgeD		s*/
313 	(void *)arm7tdmi_cache_flushID,	/* cache_purgeD_E	s*/
314 
315 	/* Other functions */
316 
317 	cpufunc_nullop,			/* flush_prefetchbuf	*/
318 	cpufunc_nullop,			/* drain_writebuf	*/
319 	cpufunc_nullop,			/* flush_brnchtgt_C	*/
320 	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
321 
322 	(void *)cpufunc_nullop,		/* sleep		*/
323 
324 	/* Soft functions */
325 
326 	cpufunc_nullop,			/* cache_syncI		*/
327 	(void *)cpufunc_nullop,		/* cache_cleanID_rng	*/
328 	(void *)cpufunc_nullop,		/* cache_cleanD_rng	*/
329 	(void *)arm7tdmi_cache_flushID,	/* cache_purgeID_rng	*/
330 	(void *)arm7tdmi_cache_flushID,	/* cache_purgeD_rng	*/
331 	(void *)cpufunc_nullop,		/* cache_syncI_rng	*/
332 
333 	late_abort_fixup,		/* dataabt_fixup	*/
334 	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
335 
336 	arm7tdmi_context_switch,		/* context_switch	*/
337 
338 	arm7tdmi_setup			/* cpu setup		*/
339 
340 };
341 #endif	/* CPU_ARM7TDMI */
342 
343 #ifdef CPU_ARM8
344 struct cpu_functions arm8_cpufuncs = {
345 	/* CPU functions */
346 
347 	cpufunc_id,			/* id			 */
348 
349 	/* MMU functions */
350 
351 	cpufunc_control,		/* control		*/
352 	cpufunc_domains,		/* domain		*/
353 	arm8_setttb,			/* setttb		*/
354 	cpufunc_faultstatus,		/* faultstatus		*/
355 	cpufunc_faultaddress,		/* faultaddress		*/
356 
357 	/* TLB functions */
358 
359 	arm8_tlb_flushID,		/* tlb_flushID		*/
360 	arm8_tlb_flushID_SE,		/* tlb_flushID_SE	*/
361 	arm8_tlb_flushID,		/* tlb_flushI		*/
362 	arm8_tlb_flushID_SE,		/* tlb_flushI_SE	*/
363 	arm8_tlb_flushID,		/* tlb_flushD		*/
364 	arm8_tlb_flushID_SE,		/* tlb_flushD_SE	*/
365 
366 	/* Cache functions */
367 
368 	arm8_cache_flushID,		/* cache_flushID	*/
369 	arm8_cache_flushID_E,		/* cache_flushID_SE	*/
370 	arm8_cache_flushID,		/* cache_flushI		*/
371 	arm8_cache_flushID_E,		/* cache_flushI_SE	*/
372 	arm8_cache_flushID,		/* cache_flushD		*/
373 	arm8_cache_flushID_E,		/* cache_flushD_SE	*/
374 
375 	arm8_cache_cleanID,		/* cache_cleanID	s*/
376 	arm8_cache_cleanID_E,		/* cache_cleanID_E	s*/
377 	arm8_cache_cleanID,		/* cache_cleanD		s*/
378 	arm8_cache_cleanID_E,		/* cache_cleanD_E	*/
379 
380 	arm8_cache_purgeID,		/* cache_purgeID	s*/
381 	arm8_cache_purgeID_E,		/* cache_purgeID_E	s*/
382 	arm8_cache_purgeID,		/* cache_purgeD		s*/
383 	arm8_cache_purgeID_E,		/* cache_purgeD_E	s*/
384 
385 	/* Other functions */
386 
387 	cpufunc_nullop,			/* flush_prefetchbuf	*/
388 	cpufunc_nullop,			/* drain_writebuf	*/
389 	cpufunc_nullop,			/* flush_brnchtgt_C	*/
390 	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
391 
392 	(void *)cpufunc_nullop,		/* sleep		*/
393 
394 	/* Soft functions */
395 
396 	(void *)cpufunc_nullop,		/* cache_syncI		*/
397 	(void *)arm8_cache_cleanID,	/* cache_cleanID_rng	*/
398 	(void *)arm8_cache_cleanID,	/* cache_cleanD_rng	*/
399 	(void *)arm8_cache_purgeID,	/* cache_purgeID_rng	*/
400 	(void *)arm8_cache_purgeID,	/* cache_purgeD_rng	*/
401 	(void *)cpufunc_nullop,		/* cache_syncI_rng	*/
402 
403 	cpufunc_null_fixup,		/* dataabt_fixup	*/
404 	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
405 
406 	arm8_context_switch,		/* context_switch	*/
407 
408 	arm8_setup			/* cpu setup		*/
409 };
410 #endif	/* CPU_ARM8 */
411 
412 #ifdef CPU_SA110
413 struct cpu_functions sa110_cpufuncs = {
414 	/* CPU functions */
415 
416 	cpufunc_id,			/* id			 */
417 
418 	/* MMU functions */
419 
420 	cpufunc_control,		/* control		*/
421 	cpufunc_domains,		/* domain		*/
422 	sa110_setttb,			/* setttb		*/
423 	cpufunc_faultstatus,		/* faultstatus		*/
424 	cpufunc_faultaddress,		/* faultaddress		*/
425 
426 	/* TLB functions */
427 
428 	sa110_tlb_flushID,		/* tlb_flushID		*/
429 	sa110_tlb_flushID_SE,		/* tlb_flushID_SE		*/
430 	sa110_tlb_flushI,		/* tlb_flushI		*/
431 	(void *)sa110_tlb_flushI,	/* tlb_flushI_SE	*/
432 	sa110_tlb_flushD,		/* tlb_flushD		*/
433 	sa110_tlb_flushD_SE,		/* tlb_flushD_SE	*/
434 
435 	/* Cache functions */
436 
437 	sa110_cache_flushID,		/* cache_flushID	*/
438 	(void *)sa110_cache_flushID,	/* cache_flushID_SE	*/
439 	sa110_cache_flushI,		/* cache_flushI		*/
440 	(void *)sa110_cache_flushI,	/* cache_flushI_SE	*/
441 	sa110_cache_flushD,		/* cache_flushD		*/
442 	sa110_cache_flushD_SE,		/* cache_flushD_SE	*/
443 
444 	sa110_cache_cleanID,		/* cache_cleanID	s*/
445 	sa110_cache_cleanD_E,		/* cache_cleanID_E	s*/
446 	sa110_cache_cleanD,		/* cache_cleanD		s*/
447 	sa110_cache_cleanD_E,		/* cache_cleanD_E	*/
448 
449 	sa110_cache_purgeID,		/* cache_purgeID	s*/
450 	sa110_cache_purgeID_E,		/* cache_purgeID_E	s*/
451 	sa110_cache_purgeD,		/* cache_purgeD		s*/
452 	sa110_cache_purgeD_E,		/* cache_purgeD_E	s*/
453 
454 	/* Other functions */
455 
456 	cpufunc_nullop,			/* flush_prefetchbuf	*/
457 	sa110_drain_writebuf,		/* drain_writebuf	*/
458 	cpufunc_nullop,			/* flush_brnchtgt_C	*/
459 	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
460 
461 	(void *)cpufunc_nullop,		/* sleep		*/
462 
463 	/* Soft functions */
464 
465 	sa110_cache_syncI,		/* cache_syncI		*/
466 	sa110_cache_cleanID_rng,	/* cache_cleanID_rng	*/
467 	sa110_cache_cleanD_rng,		/* cache_cleanD_rng	*/
468 	sa110_cache_purgeID_rng,	/* cache_purgeID_rng	*/
469 	sa110_cache_purgeD_rng,		/* cache_purgeD_rng	*/
470 	sa110_cache_syncI_rng,		/* cache_syncI_rng	*/
471 
472 	cpufunc_null_fixup,		/* dataabt_fixup	*/
473 	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
474 
475 	sa110_context_switch,		/* context_switch	*/
476 
477 	sa110_setup			/* cpu setup		*/
478 };
479 #endif	/* CPU_SA110 */
480 
481 
482 /*
483  * Global constants also used by locore.s
484  */
485 
486 struct cpu_functions cpufuncs;
487 u_int cputype;
488 u_int cpu_reset_needs_v4_MMU_disable;	/* flag used in locore.s */
489 
490 /*
491  * Cannot panic here as we may not have a console yet ...
492  */
493 
494 int
495 set_cpufuncs()
496 {
497 	cputype = cpufunc_id();
498 	cputype &= CPU_ID_CPU_MASK;
499 
500 
501 #ifdef CPU_ARM3
502 	if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD &&
503 	    (cputype & 0x00000f00) == 0x00000300) {
504 		cpufuncs = arm3_cpufuncs;
505 		cpu_reset_needs_v4_MMU_disable = 0;
506 		return 0;
507 	}
508 #endif	/* CPU_ARM3 */
509 #ifdef CPU_ARM6
510 	if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD &&
511 	    (cputype & 0x00000f00) == 0x00000600) {
512 		cpufuncs = arm6_cpufuncs;
513 		cpu_reset_needs_v4_MMU_disable = 0;
514 		return 0;
515 	}
516 #endif	/* CPU_ARM6 */
517 #ifdef CPU_ARM7
518 	if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD &&
519 	    CPU_ID_IS7(cputype) &&
520 	    (cputype & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V3) {
521 		cpufuncs = arm7_cpufuncs;
522 		cpu_reset_needs_v4_MMU_disable = 0;
523 		return 0;
524 	}
525 #endif	/* CPU_ARM7 */
526 #ifdef CPU_ARM7TDMI
527 	if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD &&
528 	    CPU_ID_IS7(cputype) &&
529 	    (cputype & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V4T) {
530 		cpufuncs = arm7tdmi_cpufuncs;
531 		cpu_reset_needs_v4_MMU_disable = 0;
532 		return 0;
533 	}
534 #endif
535 #ifdef CPU_ARM8
536 	if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD &&
537 	    (cputype & 0x0000f000) == 0x00008000) {
538 		cpufuncs = arm8_cpufuncs;
539 		cpu_reset_needs_v4_MMU_disable = 0;	/* XXX correct? */
540 		return 0;
541 	}
542 #endif	/* CPU_ARM8 */
543 #ifdef CPU_SA110
544 	if (cputype == CPU_ID_SA110 || cputype == CPU_ID_SA1100 ||
545 	    cputype == CPU_ID_SA1110) {
546 		cpufuncs = sa110_cpufuncs;
547 		cpu_reset_needs_v4_MMU_disable = 1;	/* SA needs it	*/
548 		return 0;
549 	}
550 #endif	/* CPU_SA110 */
551 	/*
552 	 * Bzzzz. And the answer was ...
553 	 */
554 /*	panic("No support for this CPU type (%08x) in kernel", cputype);*/
555 	return(ARCHITECTURE_NOT_PRESENT);
556 }
557 
558 /*
559  * Fixup routines for data and prefetch aborts.
560  *
561  * Several compile time symbols are used
562  *
563  * DEBUG_FAULT_CORRECTION - Print debugging information during the
564  * correction of registers after a fault.
565  * ARM6_LATE_ABORT - ARM6 supports both early and late aborts
566  * when defined should use late aborts
567  */
568 
569 #if defined(DEBUG_FAULT_CORRECTION) && !defined(PMAP_DEBUG)
570 #error PMAP_DEBUG must be defined to use DEBUG_FAULT_CORRECTION
571 #endif
572 
573 /*
574  * Null abort fixup routine.
575  * For use when no fixup is required.
576  */
577 int
578 cpufunc_null_fixup(arg)
579 	void *arg;
580 {
581 	return(ABORT_FIXUP_OK);
582 }
583 
584 #if defined(CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI)
585 #ifdef DEBUG_FAULT_CORRECTION
586 extern int pmap_debug_level;
587 #endif
588 #endif
589 
590 #if defined(CPU_ARM2) || defined(CPU_ARM250) || defined(CPU_ARM3) || \
591     defined(CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI)
592 /*
593  * "Early" data abort fixup.
594  *
595  * For ARM2, ARM2as, ARM3 and ARM6 (in early-abort mode).  Also used
596  * indirectly by ARM6 (in late-abort mode) and ARM7[TDMI].
597  *
598  * In early aborts, we may have to fix up LDM, STM, LDC and STC.
599  */
600 int
601 early_abort_fixup(arg)
602 	void *arg;
603 {
604 	trapframe_t *frame = arg;
605 	u_int fault_pc;
606 	u_int fault_instruction;
607 	int saved_lr = 0;
608 
609 	if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
610 
611 		/* Ok an abort in SVC mode */
612 
613 		/*
614 		 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage
615 		 * as the fault happened in svc mode but we need it in the
616 		 * usr slot so we can treat the registers as an array of ints
617 		 * during fixing.
618 		 * NOTE: This PC is in the position but writeback is not
619 		 * allowed on r15.
620 		 * Doing it like this is more efficient than trapping this
621 		 * case in all possible locations in the following fixup code.
622 		 */
623 
624 		saved_lr = frame->tf_usr_lr;
625 		frame->tf_usr_lr = frame->tf_svc_lr;
626 
627 		/*
628 		 * Note the trapframe does not have the SVC r13 so a fault
629 		 * from an instruction with writeback to r13 in SVC mode is
630 		 * not allowed. This should not happen as the kstack is
631 		 * always valid.
632 		 */
633 	}
634 
635 	/* Get fault address and status from the CPU */
636 
637 	fault_pc = frame->tf_pc;
638 	fault_instruction = *((volatile unsigned int *)fault_pc);
639 
640 	/* Decode the fault instruction and fix the registers as needed */
641 
642 	if ((fault_instruction & 0x0e000000) == 0x08000000) {
643 		int base;
644 		int loop;
645 		int count;
646 		int *registers = &frame->tf_r0;
647 
648 #ifdef DEBUG_FAULT_CORRECTION
649 		if (pmap_debug_level >= 0) {
650 			printf("LDM/STM\n");
651 			disassemble(fault_pc);
652 		}
653 #endif	/* DEBUG_FAULT_CORRECTION */
654 		if (fault_instruction & (1 << 21)) {
655 #ifdef DEBUG_FAULT_CORRECTION
656 			if (pmap_debug_level >= 0)
657 				printf("This instruction must be corrected\n");
658 #endif	/* DEBUG_FAULT_CORRECTION */
659 			base = (fault_instruction >> 16) & 0x0f;
660 			if (base == 15)
661 				return ABORT_FIXUP_FAILED;
662 			/* Count registers transferred */
663 			count = 0;
664 			for (loop = 0; loop < 16; ++loop) {
665 				if (fault_instruction & (1<<loop))
666 					++count;
667 			}
668 #ifdef DEBUG_FAULT_CORRECTION
669 			if (pmap_debug_level >= 0) {
670 				printf("%d registers used\n", count);
671 				printf("Corrected r%d by %d bytes ", base, count * 4);
672 			}
673 #endif	/* DEBUG_FAULT_CORRECTION */
674 			if (fault_instruction & (1 << 23)) {
675 #ifdef DEBUG_FAULT_CORRECTION
676 				if (pmap_debug_level >= 0)
677 					printf("down\n");
678 #endif	/* DEBUG_FAULT_CORRECTION */
679 				registers[base] -= count * 4;
680 			} else {
681 #ifdef DEBUG_FAULT_CORRECTION
682 				if (pmap_debug_level >= 0)
683 					printf("up\n");
684 #endif	/* DEBUG_FAULT_CORRECTION */
685 				registers[base] += count * 4;
686 			}
687 		}
688 	} else if ((fault_instruction & 0x0e000000) == 0x0c000000) {
689 		int base;
690 		int offset;
691 		int *registers = &frame->tf_r0;
692 
693 /* REGISTER CORRECTION IS REQUIRED FOR THESE INSTRUCTIONS */
694 
695 #ifdef DEBUG_FAULT_CORRECTION
696 		if (pmap_debug_level >= 0)
697 			disassemble(fault_pc);
698 #endif	/* DEBUG_FAULT_CORRECTION */
699 
700 /* Only need to fix registers if write back is turned on */
701 
702 		if ((fault_instruction & (1 << 21)) != 0) {
703 			base = (fault_instruction >> 16) & 0x0f;
704 			if (base == 13 && (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE)
705 				return ABORT_FIXUP_FAILED;
706 			if (base == 15)
707 				return ABORT_FIXUP_FAILED;
708 
709 			offset = (fault_instruction & 0xff) << 2;
710 #ifdef DEBUG_FAULT_CORRECTION
711 			if (pmap_debug_level >= 0)
712 				printf("r%d=%08x\n", base, registers[base]);
713 #endif	/* DEBUG_FAULT_CORRECTION */
714 			if ((fault_instruction & (1 << 23)) != 0)
715 				offset = -offset;
716 			registers[base] += offset;
717 #ifdef DEBUG_FAULT_CORRECTION
718 			if (pmap_debug_level >= 0)
719 				printf("r%d=%08x\n", base, registers[base]);
720 #endif	/* DEBUG_FAULT_CORRECTION */
721 		}
722 	} else if ((fault_instruction & 0x0e000000) == 0x0c000000)
723 		return ABORT_FIXUP_FAILED;
724 
725 	if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
726 
727 		/* Ok an abort in SVC mode */
728 
729 		/*
730 		 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage
731 		 * as the fault happened in svc mode but we need it in the
732 		 * usr slot so we can treat the registers as an array of ints
733 		 * during fixing.
734 		 * NOTE: This PC is in the position but writeback is not
735 		 * allowed on r15.
736 		 * Doing it like this is more efficient than trapping this
737 		 * case in all possible locations in the prior fixup code.
738 		 */
739 
740 		frame->tf_svc_lr = frame->tf_usr_lr;
741 		frame->tf_usr_lr = saved_lr;
742 
743 		/*
744 		 * Note the trapframe does not have the SVC r13 so a fault
745 		 * from an instruction with writeback to r13 in SVC mode is
746 		 * not allowed. This should not happen as the kstack is
747 		 * always valid.
748 		 */
749 	}
750 
751 	return(ABORT_FIXUP_OK);
752 }
753 #endif	/* CPU_ARM2/250/3/6/7 */
754 
755 #if (defined(CPU_ARM6) && defined(ARM6_LATE_ABORT)) || defined(CPU_ARM7) || \
756 	defined(CPU_ARM7TDMI)
757 /*
758  * "Late" (base updated) data abort fixup
759  *
760  * For ARM6 (in late-abort mode) and ARM7.
761  *
762  * In this model, all data-transfer instructions need fixing up.  We defer
763  * LDM, STM, LDC and STC fixup to the early-abort handler.
764  */
765 int
766 late_abort_fixup(arg)
767 	void *arg;
768 {
769 	trapframe_t *frame = arg;
770 	u_int fault_pc;
771 	u_int fault_instruction;
772 	int saved_lr = 0;
773 
774 	if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
775 
776 		/* Ok an abort in SVC mode */
777 
778 		/*
779 		 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage
780 		 * as the fault happened in svc mode but we need it in the
781 		 * usr slot so we can treat the registers as an array of ints
782 		 * during fixing.
783 		 * NOTE: This PC is in the position but writeback is not
784 		 * allowed on r15.
785 		 * Doing it like this is more efficient than trapping this
786 		 * case in all possible locations in the following fixup code.
787 		 */
788 
789 		saved_lr = frame->tf_usr_lr;
790 		frame->tf_usr_lr = frame->tf_svc_lr;
791 
792 		/*
793 		 * Note the trapframe does not have the SVC r13 so a fault
794 		 * from an instruction with writeback to r13 in SVC mode is
795 		 * not allowed. This should not happen as the kstack is
796 		 * always valid.
797 		 */
798 	}
799 
800 	/* Get fault address and status from the CPU */
801 
802 	fault_pc = frame->tf_pc;
803 	fault_instruction = *((volatile unsigned int *)fault_pc);
804 
805 	/* Decode the fault instruction and fix the registers as needed */
806 
807 	/* Was is a swap instruction ? */
808 
809 	if ((fault_instruction & 0x0fb00ff0) == 0x01000090) {
810 #ifdef DEBUG_FAULT_CORRECTION
811 		if (pmap_debug_level >= 0)
812 			disassemble(fault_pc);
813 #endif	/* DEBUG_FAULT_CORRECTION */
814 	} else if ((fault_instruction & 0x0c000000) == 0x04000000) {
815 
816 		/* Was is a ldr/str instruction */
817 		/* This is for late abort only */
818 
819 		int base;
820 		int offset;
821 		int *registers = &frame->tf_r0;
822 
823 #ifdef DEBUG_FAULT_CORRECTION
824 		if (pmap_debug_level >= 0)
825 			disassemble(fault_pc);
826 #endif	/* DEBUG_FAULT_CORRECTION */
827 
828 		/* This is for late abort only */
829 
830 		if ((fault_instruction & (1 << 24)) == 0
831 		    || (fault_instruction & (1 << 21)) != 0) {
832 			base = (fault_instruction >> 16) & 0x0f;
833 			if (base == 13 && (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE)
834 				return ABORT_FIXUP_FAILED;
835 			if (base == 15)
836 				return ABORT_FIXUP_FAILED;
837 #ifdef DEBUG_FAULT_CORRECTION
838 			if (pmap_debug_level >=0)
839 				printf("late abt fix: r%d=%08x ", base, registers[base]);
840 #endif	/* DEBUG_FAULT_CORRECTION */
841 			if ((fault_instruction & (1 << 25)) == 0) {
842 				/* Immediate offset - easy */
843 				offset = fault_instruction & 0xfff;
844 				if ((fault_instruction & (1 << 23)))
845 					offset = -offset;
846 				registers[base] += offset;
847 #ifdef DEBUG_FAULT_CORRECTION
848 				if (pmap_debug_level >=0)
849 					printf("imm=%08x ", offset);
850 #endif	/* DEBUG_FAULT_CORRECTION */
851 			} else {
852 				int shift;
853 
854 				offset = fault_instruction & 0x0f;
855 				if (offset == base)
856 					return ABORT_FIXUP_FAILED;
857 
858 /* Register offset - hard we have to cope with shifts ! */
859 				offset = registers[offset];
860 
861 				if ((fault_instruction & (1 << 4)) == 0)
862 					shift = (fault_instruction >> 7) & 0x1f;
863 				else {
864 					if ((fault_instruction & (1 << 7)) != 0)
865 						return ABORT_FIXUP_FAILED;
866 					shift = ((fault_instruction >> 8) & 0xf);
867 					if (base == shift)
868 						return ABORT_FIXUP_FAILED;
869 #ifdef DEBUG_FAULT_CORRECTION
870 					if (pmap_debug_level >=0)
871 						printf("shift reg=%d ", shift);
872 #endif	/* DEBUG_FAULT_CORRECTION */
873 					shift = registers[shift];
874 				}
875 #ifdef DEBUG_FAULT_CORRECTION
876 				if (pmap_debug_level >=0)
877 					printf("shift=%08x ", shift);
878 #endif	/* DEBUG_FAULT_CORRECTION */
879 				switch (((fault_instruction >> 5) & 0x3)) {
880 				case 0 : /* Logical left */
881 					offset = (int)(((u_int)offset) << shift);
882 					break;
883 				case 1 : /* Logical Right */
884 					if (shift == 0) shift = 32;
885 					offset = (int)(((u_int)offset) >> shift);
886 					break;
887 				case 2 : /* Arithmetic Right */
888 					if (shift == 0) shift = 32;
889 					offset = (int)(((int)offset) >> shift);
890 					break;
891 				case 3 : /* Rotate right */
892 					return ABORT_FIXUP_FAILED;
893 				}
894 
895 #ifdef DEBUG_FAULT_CORRECTION
896 				if (pmap_debug_level >=0)
897 					printf("abt: fixed LDR/STR with register offset\n");
898 #endif	/* DEBUG_FAULT_CORRECTION */
899 				if ((fault_instruction & (1 << 23)))
900 					offset = -offset;
901 #ifdef DEBUG_FAULT_CORRECTION
902 				if (pmap_debug_level >=0)
903 					printf("offset=%08x ", offset);
904 #endif	/* DEBUG_FAULT_CORRECTION */
905 				registers[base] += offset;
906 			}
907 #ifdef DEBUG_FAULT_CORRECTION
908 			if (pmap_debug_level >=0)
909 				printf("r%d=%08x\n", base, registers[base]);
910 #endif	/* DEBUG_FAULT_CORRECTION */
911 		}
912 	}
913 
914 	if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
915 
916 		/* Ok an abort in SVC mode */
917 
918 		/*
919 		 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage
920 		 * as the fault happened in svc mode but we need it in the
921 		 * usr slot so we can treat the registers as an array of ints
922 		 * during fixing.
923 		 * NOTE: This PC is in the position but writeback is not
924 		 * allowed on r15.
925 		 * Doing it like this is more efficient than trapping this
926 		 * case in all possible locations in the prior fixup code.
927 		 */
928 
929 		frame->tf_svc_lr = frame->tf_usr_lr;
930 		frame->tf_usr_lr = saved_lr;
931 
932 		/*
933 		 * Note the trapframe does not have the SVC r13 so a fault
934 		 * from an instruction with writeback to r13 in SVC mode is
935 		 * not allowed. This should not happen as the kstack is
936 		 * always valid.
937 		 */
938 	}
939 
940 	/*
941 	 * Now let the early-abort fixup routine have a go, in case it
942 	 * was an LDM, STM, LDC or STC that faulted.
943 	 */
944 
945 	return early_abort_fixup(arg);
946 }
947 #endif	/* CPU_ARM6(LATE)/7/7TDMI */
948 
949 /*
950  * CPU Setup code
951  */
952 
953 #if defined(CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI) || \
954 	defined(CPU_ARM8) || defined(CPU_SA110)
955 int cpuctrl;
956 
957 #define IGN	0
958 #define OR	1
959 #define BIC	2
960 
961 struct cpu_option {
962 	char	*co_name;
963 	int	co_falseop;
964 	int	co_trueop;
965 	int	co_value;
966 };
967 
968 static u_int
969 parse_cpu_options(args, optlist, cpuctrl)
970 	char *args;
971 	struct cpu_option *optlist;
972 	u_int cpuctrl;
973 {
974 	int integer;
975 
976 	while (optlist->co_name) {
977 		if (get_bootconf_option(args, optlist->co_name,
978 		    BOOTOPT_TYPE_BOOLEAN, &integer)) {
979 			if (integer) {
980 				if (optlist->co_trueop == OR)
981 					cpuctrl |= optlist->co_value;
982 				else if (optlist->co_trueop == BIC)
983 					cpuctrl &= ~optlist->co_value;
984 			} else {
985 				if (optlist->co_falseop == OR)
986 					cpuctrl |= optlist->co_value;
987 				else if (optlist->co_falseop == BIC)
988 					cpuctrl &= ~optlist->co_value;
989 			}
990 		}
991 		++optlist;
992 	}
993 	return(cpuctrl);
994 }
995 #endif /* CPU_ARM6 || CPU_ARM7 || CPU_ARM7TDMI || CPU_ARM8 || CPU_SA110 */
996 
997 #if defined (CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI) \
998 	|| defined(CPU_ARM8)
999 struct cpu_option arm678_options[] = {
1000 #ifdef COMPAT_12
1001 	{ "nocache",		IGN, BIC, CPU_CONTROL_IDC_ENABLE },
1002 	{ "nowritebuf",		IGN, BIC, CPU_CONTROL_WBUF_ENABLE },
1003 #endif	/* COMPAT_12 */
1004 	{ "cpu.cache",		BIC, OR,  CPU_CONTROL_IDC_ENABLE },
1005 	{ "cpu.nocache",	OR,  BIC, CPU_CONTROL_IDC_ENABLE },
1006 	{ "cpu.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1007 	{ "cpu.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1008 	{ NULL,			IGN, IGN, 0 }
1009 };
1010 
1011 #endif	/* CPU_ARM6 || CPU_ARM7 || CPU_ARM7TDMI || CPU_ARM8 */
1012 
1013 #ifdef CPU_ARM6
1014 struct cpu_option arm6_options[] = {
1015 	{ "arm6.cache",		BIC, OR,  CPU_CONTROL_IDC_ENABLE },
1016 	{ "arm6.nocache",	OR,  BIC, CPU_CONTROL_IDC_ENABLE },
1017 	{ "arm6.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1018 	{ "arm6.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1019 	{ NULL,			IGN, IGN, 0 }
1020 };
1021 
1022 void
1023 arm6_setup(args)
1024 	char *args;
1025 {
1026 	int cpuctrlmask;
1027 
1028 	/* Set up default control registers bits */
1029 	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1030 		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1031 		 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE;
1032 	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1033 		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1034 		 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE
1035 		 | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_BEND_ENABLE
1036 		 | CPU_CONTROL_AFLT_ENABLE;
1037 
1038 #ifdef ARM6_LATE_ABORT
1039 	cpuctrl |= CPU_CONTROL_LABT_ENABLE;
1040 #endif	/* ARM6_LATE_ABORT */
1041 
1042 	cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl);
1043 	cpuctrl = parse_cpu_options(args, arm6_options, cpuctrl);
1044 
1045 	/* Clear out the cache */
1046 	cpu_cache_purgeID();
1047 
1048 	/* Set the control register */
1049 	cpu_control(0xffffffff, cpuctrl);
1050 }
1051 #endif	/* CPU_ARM6 */
1052 
1053 #ifdef CPU_ARM7
1054 struct cpu_option arm7_options[] = {
1055 	{ "arm7.cache",		BIC, OR,  CPU_CONTROL_IDC_ENABLE },
1056 	{ "arm7.nocache",	OR,  BIC, CPU_CONTROL_IDC_ENABLE },
1057 	{ "arm7.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1058 	{ "arm7.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1059 #ifdef COMPAT_12
1060 	{ "fpaclk2",		BIC, OR,  CPU_CONTROL_CPCLK },
1061 #endif	/* COMPAT_12 */
1062 	{ "arm700.fpaclk",	BIC, OR,  CPU_CONTROL_CPCLK },
1063 	{ NULL,			IGN, IGN, 0 }
1064 };
1065 
1066 void
1067 arm7_setup(args)
1068 	char *args;
1069 {
1070 	int cpuctrlmask;
1071 
1072 	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1073 		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1074 		 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE;
1075 	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1076 		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1077 		 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE
1078 		 | CPU_CONTROL_CPCLK | CPU_CONTROL_LABT_ENABLE
1079 		 | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_BEND_ENABLE
1080 		 | CPU_CONTROL_AFLT_ENABLE;
1081 
1082 	cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl);
1083 	cpuctrl = parse_cpu_options(args, arm7_options, cpuctrl);
1084 
1085 	/* Clear out the cache */
1086 	cpu_cache_purgeID();
1087 
1088 	/* Set the control register */
1089 	cpu_control(0xffffffff, cpuctrl);
1090 }
1091 #endif	/* CPU_ARM7 */
1092 
1093 #ifdef CPU_ARM7TDMI
1094 struct cpu_option arm7tdmi_options[] = {
1095 	{ "arm7.cache",		BIC, OR,  CPU_CONTROL_IDC_ENABLE },
1096 	{ "arm7.nocache",	OR,  BIC, CPU_CONTROL_IDC_ENABLE },
1097 	{ "arm7.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1098 	{ "arm7.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1099 #ifdef COMPAT_12
1100 	{ "fpaclk2",		BIC, OR,  CPU_CONTROL_CPCLK },
1101 #endif	/* COMPAT_12 */
1102 	{ "arm700.fpaclk",	BIC, OR,  CPU_CONTROL_CPCLK },
1103 	{ NULL,			IGN, IGN, 0 }
1104 };
1105 
1106 void
1107 arm7tdmi_setup(args)
1108 	char *args;
1109 {
1110 	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1111 		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1112 		 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE;
1113 
1114 	cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl);
1115 	cpuctrl = parse_cpu_options(args, arm7tdmi_options, cpuctrl);
1116 
1117 	/* Clear out the cache */
1118 	cpu_cache_purgeID();
1119 
1120 	/* Set the control register */
1121 	cpu_control(0xffffffff, cpuctrl);
1122 }
1123 #endif	/* CPU_ARM7TDMI */
1124 
1125 #ifdef CPU_ARM8
1126 struct cpu_option arm8_options[] = {
1127 	{ "arm8.cache",		BIC, OR,  CPU_CONTROL_IDC_ENABLE },
1128 	{ "arm8.nocache",	OR,  BIC, CPU_CONTROL_IDC_ENABLE },
1129 	{ "arm8.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1130 	{ "arm8.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1131 #ifdef COMPAT_12
1132 	{ "branchpredict", 	BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
1133 #endif	/* COMPAT_12 */
1134 	{ "cpu.branchpredict", 	BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
1135 	{ "arm8.branchpredict",	BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
1136 	{ NULL,			IGN, IGN, 0 }
1137 };
1138 
1139 void
1140 arm8_setup(args)
1141 	char *args;
1142 {
1143 	int integer;
1144 	int cpuctrlmask;
1145 	int clocktest;
1146 	int setclock = 0;
1147 
1148 	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1149 		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1150 		 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE;
1151 	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1152 		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1153 		 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE
1154 		 | CPU_CONTROL_BPRD_ENABLE | CPU_CONTROL_ROM_ENABLE
1155 		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE;
1156 
1157 	cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl);
1158 	cpuctrl = parse_cpu_options(args, arm8_options, cpuctrl);
1159 
1160 	/* Get clock configuration */
1161 	clocktest = arm8_clock_config(0, 0) & 0x0f;
1162 
1163 	/* Special ARM8 clock and test configuration */
1164 	if (get_bootconf_option(args, "arm8.clock.reset", BOOTOPT_TYPE_BOOLEAN, &integer)) {
1165 		clocktest = 0;
1166 		setclock = 1;
1167 	}
1168 	if (get_bootconf_option(args, "arm8.clock.dynamic", BOOTOPT_TYPE_BOOLEAN, &integer)) {
1169 		if (integer)
1170 			clocktest |= 0x01;
1171 		else
1172 			clocktest &= ~(0x01);
1173 		setclock = 1;
1174 	}
1175 	if (get_bootconf_option(args, "arm8.clock.sync", BOOTOPT_TYPE_BOOLEAN, &integer)) {
1176 		if (integer)
1177 			clocktest |= 0x02;
1178 		else
1179 			clocktest &= ~(0x02);
1180 		setclock = 1;
1181 	}
1182 	if (get_bootconf_option(args, "arm8.clock.fast", BOOTOPT_TYPE_BININT, &integer)) {
1183 		clocktest = (clocktest & ~0xc0) | (integer & 3) << 2;
1184 		setclock = 1;
1185 	}
1186 	if (get_bootconf_option(args, "arm8.test", BOOTOPT_TYPE_BININT, &integer)) {
1187 		clocktest |= (integer & 7) << 5;
1188 		setclock = 1;
1189 	}
1190 
1191 	/* Clear out the cache */
1192 	cpu_cache_purgeID();
1193 
1194 	/* Set the control register */
1195 	cpu_control(0xffffffff, cpuctrl);
1196 
1197 	/* Set the clock/test register */
1198 	if (setclock)
1199 		arm8_clock_config(0x7f, clocktest);
1200 }
1201 #endif	/* CPU_ARM8 */
1202 
1203 #ifdef CPU_SA110
1204 struct cpu_option sa110_options[] = {
1205 #ifdef COMPAT_12
1206 	{ "nocache",		IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1207 	{ "nowritebuf",		IGN, BIC, CPU_CONTROL_WBUF_ENABLE },
1208 #endif	/* COMPAT_12 */
1209 	{ "cpu.cache",		BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1210 	{ "cpu.nocache",	OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1211 	{ "sa110.cache",	BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1212 	{ "sa110.icache",	BIC, OR,  CPU_CONTROL_IC_ENABLE },
1213 	{ "sa110.dcache",	BIC, OR,  CPU_CONTROL_DC_ENABLE },
1214 	{ "cpu.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1215 	{ "cpu.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1216 	{ "sa110.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1217 	{ NULL,			IGN, IGN, 0 }
1218 };
1219 
1220 void
1221 sa110_setup(args)
1222 	char *args;
1223 {
1224 	int cpuctrlmask;
1225 
1226 	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1227 		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1228 		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1229 		 | CPU_CONTROL_WBUF_ENABLE;
1230 	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1231 		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1232 		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1233 		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
1234 		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
1235 		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
1236 		 | CPU_CONTROL_CPCLK;
1237 
1238 	cpuctrl = parse_cpu_options(args, sa110_options, cpuctrl);
1239 
1240 	/* Clear out the cache */
1241 	cpu_cache_purgeID();
1242 
1243 	/* Set the control register */
1244 /*	cpu_control(cpuctrlmask, cpuctrl);*/
1245 	cpu_control(0xffffffff, cpuctrl);
1246 
1247 	/* enable clockswitching */
1248 	__asm ("mcr 15, 0, r0, c15, c1, 2");
1249 }
1250 #endif	/* CPU_SA110 */
1251