cpufunc.c revision 146605
1129198Scognet/*	$NetBSD: cpufunc.c,v 1.65 2003/11/05 12:53:15 scw Exp $	*/
2129198Scognet
3139735Simp/*-
4129198Scognet * arm7tdmi support code Copyright (c) 2001 John Fremlin
5129198Scognet * arm8 support code Copyright (c) 1997 ARM Limited
6129198Scognet * arm8 support code Copyright (c) 1997 Causality Limited
7129198Scognet * arm9 support code Copyright (C) 2001 ARM Ltd
8129198Scognet * Copyright (c) 1997 Mark Brinicombe.
9129198Scognet * Copyright (c) 1997 Causality Limited
10129198Scognet * All rights reserved.
11129198Scognet *
12129198Scognet * Redistribution and use in source and binary forms, with or without
13129198Scognet * modification, are permitted provided that the following conditions
14129198Scognet * are met:
15129198Scognet * 1. Redistributions of source code must retain the above copyright
16129198Scognet *    notice, this list of conditions and the following disclaimer.
17129198Scognet * 2. Redistributions in binary form must reproduce the above copyright
18129198Scognet *    notice, this list of conditions and the following disclaimer in the
19129198Scognet *    documentation and/or other materials provided with the distribution.
20129198Scognet * 3. All advertising materials mentioning features or use of this software
21129198Scognet *    must display the following acknowledgement:
22129198Scognet *	This product includes software developed by Causality Limited.
23129198Scognet * 4. The name of Causality Limited may not be used to endorse or promote
24129198Scognet *    products derived from this software without specific prior written
25129198Scognet *    permission.
26129198Scognet *
27129198Scognet * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
28129198Scognet * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29129198Scognet * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
30129198Scognet * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
31129198Scognet * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32129198Scognet * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33129198Scognet * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34129198Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35129198Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36129198Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37129198Scognet * SUCH DAMAGE.
38129198Scognet *
39129198Scognet * RiscBSD kernel project
40129198Scognet *
41129198Scognet * cpufuncs.c
42129198Scognet *
43129198Scognet * C functions for supporting CPU / MMU / TLB specific operations.
44129198Scognet *
45129198Scognet * Created      : 30/01/97
46129198Scognet */
47129198Scognet#include <sys/cdefs.h>
48129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/cpufunc.c 146605 2005-05-24 23:57:22Z cognet $");
49129198Scognet
50129198Scognet#include <sys/cdefs.h>
51129198Scognet
52129198Scognet#include <sys/types.h>
53129198Scognet#include <sys/param.h>
54129198Scognet#include <sys/systm.h>
55129198Scognet#include <sys/lock.h>
56129198Scognet#include <sys/mutex.h>
57132472Scognet#include <sys/bus.h>
58132472Scognet#include <machine/bus.h>
59129198Scognet#include <machine/cpu.h>
60129198Scognet#include <machine/disassem.h>
61129198Scognet
62129198Scognet#include <vm/vm.h>
63129198Scognet#include <vm/pmap.h>
64129198Scognet
65129198Scognet#include <machine/cpuconf.h>
66129198Scognet#include <machine/cpufunc.h>
67129198Scognet#include <machine/bootconfig.h>
68129198Scognet
69129198Scognet#ifdef CPU_XSCALE_80200
70135646Scognet#include <arm/xscale/i80200/i80200reg.h>
71135646Scognet#include <arm/xscale/i80200/i80200var.h>
72129198Scognet#endif
73129198Scognet
74129198Scognet#ifdef CPU_XSCALE_80321
75135646Scognet#include <arm/xscale/i80321/i80321reg.h>
76135646Scognet#include <arm/xscale/i80321/i80321var.h>
77129198Scognet#endif
78129198Scognet
79129198Scognet#ifdef CPU_XSCALE_IXP425
80135646Scognet#include <arm/xscale/ixp425/ixp425reg.h>
81135646Scognet#include <arm/xscale/ixp425/ixp425var.h>
82129198Scognet#endif
83129198Scognet
84129198Scognet#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321)
85129198Scognet#include <arm/xscale/xscalereg.h>
86129198Scognet#endif
87129198Scognet
88129198Scognet#if defined(PERFCTRS)
89129198Scognetstruct arm_pmc_funcs *arm_pmc;
90129198Scognet#endif
91129198Scognet
92129198Scognet/* PRIMARY CACHE VARIABLES */
93129198Scognetint	arm_picache_size;
94129198Scognetint	arm_picache_line_size;
95129198Scognetint	arm_picache_ways;
96129198Scognet
97129198Scognetint	arm_pdcache_size;	/* and unified */
98129198Scognetint	arm_pdcache_line_size;
99129198Scognetint	arm_pdcache_ways;
100129198Scognet
101129198Scognetint	arm_pcache_type;
102129198Scognetint	arm_pcache_unified;
103129198Scognet
104129198Scognetint	arm_dcache_align;
105129198Scognetint	arm_dcache_align_mask;
106129198Scognet
107129198Scognet/* 1 == use cpu_sleep(), 0 == don't */
108129198Scognetint cpu_do_powersave;
109129198Scognetint ctrl;
110129198Scognet#ifdef CPU_ARM3
111129198Scognetstruct cpu_functions arm3_cpufuncs = {
112129198Scognet	/* CPU functions */
113129198Scognet
114129198Scognet	cpufunc_id,			/* id			*/
115129198Scognet	cpufunc_nullop,			/* cpwait		*/
116129198Scognet
117129198Scognet	/* MMU functions */
118129198Scognet
119129198Scognet	arm3_control,			/* control		*/
120129198Scognet	NULL,				/* domain		*/
121129198Scognet	NULL,				/* setttb		*/
122129198Scognet	NULL,				/* faultstatus		*/
123129198Scognet	NULL,				/* faultaddress		*/
124129198Scognet
125129198Scognet	/* TLB functions */
126129198Scognet
127129198Scognet	cpufunc_nullop,			/* tlb_flushID		*/
128129198Scognet	(void *)cpufunc_nullop,		/* tlb_flushID_SE	*/
129129198Scognet	cpufunc_nullop,			/* tlb_flushI		*/
130129198Scognet	(void *)cpufunc_nullop,		/* tlb_flushI_SE	*/
131129198Scognet	cpufunc_nullop,			/* tlb_flushD		*/
132129198Scognet	(void *)cpufunc_nullop,		/* tlb_flushD_SE	*/
133129198Scognet
134129198Scognet	/* Cache operations */
135129198Scognet
136129198Scognet	cpufunc_nullop,			/* icache_sync_all	*/
137129198Scognet	(void *) cpufunc_nullop,	/* icache_sync_range	*/
138129198Scognet
139129198Scognet	arm3_cache_flush,		/* dcache_wbinv_all	*/
140129198Scognet	(void *)arm3_cache_flush,	/* dcache_wbinv_range	*/
141129198Scognet	(void *)arm3_cache_flush,	/* dcache_inv_range	*/
142129198Scognet	(void *)cpufunc_nullop,		/* dcache_wb_range	*/
143129198Scognet
144129198Scognet	arm3_cache_flush,		/* idcache_wbinv_all	*/
145129198Scognet	(void *)arm3_cache_flush,	/* idcache_wbinv_range	*/
146129198Scognet
147129198Scognet	/* Other functions */
148129198Scognet
149129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
150129198Scognet	cpufunc_nullop,			/* drain_writebuf	*/
151129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
152129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
153129198Scognet
154129198Scognet	(void *)cpufunc_nullop,		/* sleep		*/
155129198Scognet
156129198Scognet	/* Soft functions */
157129198Scognet
158129198Scognet	early_abort_fixup,		/* dataabt_fixup	*/
159129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
160129198Scognet
161129198Scognet	NULL,				/* context_switch	*/
162129198Scognet
163129198Scognet	(void *)cpufunc_nullop		/* cpu setup		*/
164129198Scognet
165129198Scognet};
166129198Scognet#endif	/* CPU_ARM3 */
167129198Scognet
168129198Scognet#ifdef CPU_ARM6
169129198Scognetstruct cpu_functions arm6_cpufuncs = {
170129198Scognet	/* CPU functions */
171129198Scognet
172129198Scognet	cpufunc_id,			/* id			*/
173129198Scognet	cpufunc_nullop,			/* cpwait		*/
174129198Scognet
175129198Scognet	/* MMU functions */
176129198Scognet
177129198Scognet	cpufunc_control,		/* control		*/
178129198Scognet	cpufunc_domains,		/* domain		*/
179129198Scognet	arm67_setttb,			/* setttb		*/
180129198Scognet	cpufunc_faultstatus,		/* faultstatus		*/
181129198Scognet	cpufunc_faultaddress,		/* faultaddress		*/
182129198Scognet
183129198Scognet	/* TLB functions */
184129198Scognet
185129198Scognet	arm67_tlb_flush,		/* tlb_flushID		*/
186129198Scognet	arm67_tlb_purge,		/* tlb_flushID_SE	*/
187129198Scognet	arm67_tlb_flush,		/* tlb_flushI		*/
188129198Scognet	arm67_tlb_purge,		/* tlb_flushI_SE	*/
189129198Scognet	arm67_tlb_flush,		/* tlb_flushD		*/
190129198Scognet	arm67_tlb_purge,		/* tlb_flushD_SE	*/
191129198Scognet
192129198Scognet	/* Cache operations */
193129198Scognet
194129198Scognet	cpufunc_nullop,			/* icache_sync_all	*/
195129198Scognet	(void *) cpufunc_nullop,	/* icache_sync_range	*/
196129198Scognet
197129198Scognet	arm67_cache_flush,		/* dcache_wbinv_all	*/
198129198Scognet	(void *)arm67_cache_flush,	/* dcache_wbinv_range	*/
199129198Scognet	(void *)arm67_cache_flush,	/* dcache_inv_range	*/
200129198Scognet	(void *)cpufunc_nullop,		/* dcache_wb_range	*/
201129198Scognet
202129198Scognet	arm67_cache_flush,		/* idcache_wbinv_all	*/
203129198Scognet	(void *)arm67_cache_flush,	/* idcache_wbinv_range	*/
204129198Scognet
205129198Scognet	/* Other functions */
206129198Scognet
207129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
208129198Scognet	cpufunc_nullop,			/* drain_writebuf	*/
209129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
210129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
211129198Scognet
212129198Scognet	(void *)cpufunc_nullop,		/* sleep		*/
213129198Scognet
214129198Scognet	/* Soft functions */
215129198Scognet
216129198Scognet#ifdef ARM6_LATE_ABORT
217129198Scognet	late_abort_fixup,		/* dataabt_fixup	*/
218129198Scognet#else
219129198Scognet	early_abort_fixup,		/* dataabt_fixup	*/
220129198Scognet#endif
221129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
222129198Scognet
223129198Scognet	arm67_context_switch,		/* context_switch	*/
224129198Scognet
225129198Scognet	arm6_setup			/* cpu setup		*/
226129198Scognet
227129198Scognet};
228129198Scognet#endif	/* CPU_ARM6 */
229129198Scognet
230129198Scognet#ifdef CPU_ARM7
231129198Scognetstruct cpu_functions arm7_cpufuncs = {
232129198Scognet	/* CPU functions */
233129198Scognet
234129198Scognet	cpufunc_id,			/* id			*/
235129198Scognet	cpufunc_nullop,			/* cpwait		*/
236129198Scognet
237129198Scognet	/* MMU functions */
238129198Scognet
239129198Scognet	cpufunc_control,		/* control		*/
240129198Scognet	cpufunc_domains,		/* domain		*/
241129198Scognet	arm67_setttb,			/* setttb		*/
242129198Scognet	cpufunc_faultstatus,		/* faultstatus		*/
243129198Scognet	cpufunc_faultaddress,		/* faultaddress		*/
244129198Scognet
245129198Scognet	/* TLB functions */
246129198Scognet
247129198Scognet	arm67_tlb_flush,		/* tlb_flushID		*/
248129198Scognet	arm67_tlb_purge,		/* tlb_flushID_SE	*/
249129198Scognet	arm67_tlb_flush,		/* tlb_flushI		*/
250129198Scognet	arm67_tlb_purge,		/* tlb_flushI_SE	*/
251129198Scognet	arm67_tlb_flush,		/* tlb_flushD		*/
252129198Scognet	arm67_tlb_purge,		/* tlb_flushD_SE	*/
253129198Scognet
254129198Scognet	/* Cache operations */
255129198Scognet
256129198Scognet	cpufunc_nullop,			/* icache_sync_all	*/
257129198Scognet	(void *)cpufunc_nullop,		/* icache_sync_range	*/
258129198Scognet
259129198Scognet	arm67_cache_flush,		/* dcache_wbinv_all	*/
260129198Scognet	(void *)arm67_cache_flush,	/* dcache_wbinv_range	*/
261129198Scognet	(void *)arm67_cache_flush,	/* dcache_inv_range	*/
262129198Scognet	(void *)cpufunc_nullop,		/* dcache_wb_range	*/
263129198Scognet
264129198Scognet	arm67_cache_flush,		/* idcache_wbinv_all	*/
265129198Scognet	(void *)arm67_cache_flush,	/* idcache_wbinv_range	*/
266129198Scognet
267129198Scognet	/* Other functions */
268129198Scognet
269129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
270129198Scognet	cpufunc_nullop,			/* drain_writebuf	*/
271129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
272129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
273129198Scognet
274129198Scognet	(void *)cpufunc_nullop,		/* sleep		*/
275129198Scognet
276129198Scognet	/* Soft functions */
277129198Scognet
278129198Scognet	late_abort_fixup,		/* dataabt_fixup	*/
279129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
280129198Scognet
281129198Scognet	arm67_context_switch,		/* context_switch	*/
282129198Scognet
283129198Scognet	arm7_setup			/* cpu setup		*/
284129198Scognet
285129198Scognet};
286129198Scognet#endif	/* CPU_ARM7 */
287129198Scognet
288129198Scognet#ifdef CPU_ARM7TDMI
289129198Scognetstruct cpu_functions arm7tdmi_cpufuncs = {
290129198Scognet	/* CPU functions */
291129198Scognet
292129198Scognet	cpufunc_id,			/* id			*/
293129198Scognet	cpufunc_nullop,			/* cpwait		*/
294129198Scognet
295129198Scognet	/* MMU functions */
296129198Scognet
297129198Scognet	cpufunc_control,		/* control		*/
298129198Scognet	cpufunc_domains,		/* domain		*/
299129198Scognet	arm7tdmi_setttb,		/* setttb		*/
300129198Scognet	cpufunc_faultstatus,		/* faultstatus		*/
301129198Scognet	cpufunc_faultaddress,		/* faultaddress		*/
302129198Scognet
303129198Scognet	/* TLB functions */
304129198Scognet
305129198Scognet	arm7tdmi_tlb_flushID,		/* tlb_flushID		*/
306129198Scognet	arm7tdmi_tlb_flushID_SE,	/* tlb_flushID_SE	*/
307129198Scognet	arm7tdmi_tlb_flushID,		/* tlb_flushI		*/
308129198Scognet	arm7tdmi_tlb_flushID_SE,	/* tlb_flushI_SE	*/
309129198Scognet	arm7tdmi_tlb_flushID,		/* tlb_flushD		*/
310129198Scognet	arm7tdmi_tlb_flushID_SE,	/* tlb_flushD_SE	*/
311129198Scognet
312129198Scognet	/* Cache operations */
313129198Scognet
314129198Scognet	cpufunc_nullop,			/* icache_sync_all	*/
315129198Scognet	(void *)cpufunc_nullop,		/* icache_sync_range	*/
316129198Scognet
317129198Scognet	arm7tdmi_cache_flushID,		/* dcache_wbinv_all	*/
318129198Scognet	(void *)arm7tdmi_cache_flushID,	/* dcache_wbinv_range	*/
319129198Scognet	(void *)arm7tdmi_cache_flushID,	/* dcache_inv_range	*/
320129198Scognet	(void *)cpufunc_nullop,		/* dcache_wb_range	*/
321129198Scognet
322129198Scognet	arm7tdmi_cache_flushID,		/* idcache_wbinv_all	*/
323129198Scognet	(void *)arm7tdmi_cache_flushID,	/* idcache_wbinv_range	*/
324129198Scognet
325129198Scognet	/* Other functions */
326129198Scognet
327129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
328129198Scognet	cpufunc_nullop,			/* drain_writebuf	*/
329129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
330129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
331129198Scognet
332129198Scognet	(void *)cpufunc_nullop,		/* sleep		*/
333129198Scognet
334129198Scognet	/* Soft functions */
335129198Scognet
336129198Scognet	late_abort_fixup,		/* dataabt_fixup	*/
337129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
338129198Scognet
339129198Scognet	arm7tdmi_context_switch,	/* context_switch	*/
340129198Scognet
341129198Scognet	arm7tdmi_setup			/* cpu setup		*/
342129198Scognet
343129198Scognet};
344129198Scognet#endif	/* CPU_ARM7TDMI */
345129198Scognet
346129198Scognet#ifdef CPU_ARM8
347129198Scognetstruct cpu_functions arm8_cpufuncs = {
348129198Scognet	/* CPU functions */
349129198Scognet
350129198Scognet	cpufunc_id,			/* id			*/
351129198Scognet	cpufunc_nullop,			/* cpwait		*/
352129198Scognet
353129198Scognet	/* MMU functions */
354129198Scognet
355129198Scognet	cpufunc_control,		/* control		*/
356129198Scognet	cpufunc_domains,		/* domain		*/
357129198Scognet	arm8_setttb,			/* setttb		*/
358129198Scognet	cpufunc_faultstatus,		/* faultstatus		*/
359129198Scognet	cpufunc_faultaddress,		/* faultaddress		*/
360129198Scognet
361129198Scognet	/* TLB functions */
362129198Scognet
363129198Scognet	arm8_tlb_flushID,		/* tlb_flushID		*/
364129198Scognet	arm8_tlb_flushID_SE,		/* tlb_flushID_SE	*/
365129198Scognet	arm8_tlb_flushID,		/* tlb_flushI		*/
366129198Scognet	arm8_tlb_flushID_SE,		/* tlb_flushI_SE	*/
367129198Scognet	arm8_tlb_flushID,		/* tlb_flushD		*/
368129198Scognet	arm8_tlb_flushID_SE,		/* tlb_flushD_SE	*/
369129198Scognet
370129198Scognet	/* Cache operations */
371129198Scognet
372129198Scognet	cpufunc_nullop,			/* icache_sync_all	*/
373129198Scognet	(void *)cpufunc_nullop,		/* icache_sync_range	*/
374129198Scognet
375129198Scognet	arm8_cache_purgeID,		/* dcache_wbinv_all	*/
376129198Scognet	(void *)arm8_cache_purgeID,	/* dcache_wbinv_range	*/
377129198Scognet/*XXX*/	(void *)arm8_cache_purgeID,	/* dcache_inv_range	*/
378129198Scognet	(void *)arm8_cache_cleanID,	/* dcache_wb_range	*/
379129198Scognet
380129198Scognet	arm8_cache_purgeID,		/* idcache_wbinv_all	*/
381129198Scognet	(void *)arm8_cache_purgeID,	/* idcache_wbinv_range	*/
382129198Scognet
383129198Scognet	/* Other functions */
384129198Scognet
385129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
386129198Scognet	cpufunc_nullop,			/* drain_writebuf	*/
387129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
388129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
389129198Scognet
390129198Scognet	(void *)cpufunc_nullop,		/* sleep		*/
391129198Scognet
392129198Scognet	/* Soft functions */
393129198Scognet
394129198Scognet	cpufunc_null_fixup,		/* dataabt_fixup	*/
395129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
396129198Scognet
397129198Scognet	arm8_context_switch,		/* context_switch	*/
398129198Scognet
399129198Scognet	arm8_setup			/* cpu setup		*/
400129198Scognet};
401129198Scognet#endif	/* CPU_ARM8 */
402129198Scognet
403129198Scognet#ifdef CPU_ARM9
404129198Scognetstruct cpu_functions arm9_cpufuncs = {
405129198Scognet	/* CPU functions */
406129198Scognet
407129198Scognet	cpufunc_id,			/* id			*/
408129198Scognet	cpufunc_nullop,			/* cpwait		*/
409129198Scognet
410129198Scognet	/* MMU functions */
411129198Scognet
412129198Scognet	cpufunc_control,		/* control		*/
413129198Scognet	cpufunc_domains,		/* Domain		*/
414129198Scognet	arm9_setttb,			/* Setttb		*/
415129198Scognet	cpufunc_faultstatus,		/* Faultstatus		*/
416129198Scognet	cpufunc_faultaddress,		/* Faultaddress		*/
417129198Scognet
418129198Scognet	/* TLB functions */
419129198Scognet
420129198Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
421129198Scognet	arm9_tlb_flushID_SE,		/* tlb_flushID_SE	*/
422129198Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
423129198Scognet	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
424129198Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
425129198Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
426129198Scognet
427129198Scognet	/* Cache operations */
428129198Scognet
429146605Scognet	arm9_icache_sync_all,		/* icache_sync_all	*/
430146605Scognet	arm9_icache_sync_range,		/* icache_sync_range	*/
431129198Scognet
432146605Scognet	arm9_dcache_wbinv_all,		/* dcache_wbinv_all	*/
433146605Scognet	arm9_dcache_wbinv_range,	/* dcache_wbinv_range	*/
434146605Scognet/*XXX*/	arm9_dcache_wbinv_range,	/* dcache_inv_range	*/
435146605Scognet	arm9_dcache_wb_range,		/* dcache_wb_range	*/
436129198Scognet
437146605Scognet	arm9_idcache_wbinv_all,		/* idcache_wbinv_all	*/
438146605Scognet	arm9_idcache_wbinv_range,	/* idcache_wbinv_range	*/
439129198Scognet
440129198Scognet	/* Other functions */
441129198Scognet
442129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
443129198Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
444129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
445129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
446129198Scognet
447129198Scognet	(void *)cpufunc_nullop,		/* sleep		*/
448129198Scognet
449129198Scognet	/* Soft functions */
450129198Scognet
451129198Scognet	cpufunc_null_fixup,		/* dataabt_fixup	*/
452129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
453129198Scognet
454129198Scognet	arm9_context_switch,		/* context_switch	*/
455129198Scognet
456129198Scognet	arm9_setup			/* cpu setup		*/
457129198Scognet
458129198Scognet};
459129198Scognet#endif /* CPU_ARM9 */
460129198Scognet
461129198Scognet#ifdef CPU_ARM10
462129198Scognetstruct cpu_functions arm10_cpufuncs = {
463129198Scognet	/* CPU functions */
464129198Scognet
465129198Scognet	cpufunc_id,			/* id			*/
466129198Scognet	cpufunc_nullop,			/* cpwait		*/
467129198Scognet
468129198Scognet	/* MMU functions */
469129198Scognet
470129198Scognet	cpufunc_control,		/* control		*/
471129198Scognet	cpufunc_domains,		/* Domain		*/
472129198Scognet	arm10_setttb,			/* Setttb		*/
473129198Scognet	cpufunc_faultstatus,		/* Faultstatus		*/
474129198Scognet	cpufunc_faultaddress,		/* Faultaddress		*/
475129198Scognet
476129198Scognet	/* TLB functions */
477129198Scognet
478129198Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
479129198Scognet	arm10_tlb_flushID_SE,		/* tlb_flushID_SE	*/
480129198Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
481129198Scognet	arm10_tlb_flushI_SE,		/* tlb_flushI_SE	*/
482129198Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
483129198Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
484129198Scognet
485129198Scognet	/* Cache operations */
486129198Scognet
487129198Scognet	arm10_icache_sync_all,		/* icache_sync_all	*/
488129198Scognet	arm10_icache_sync_range,	/* icache_sync_range	*/
489129198Scognet
490129198Scognet	arm10_dcache_wbinv_all,		/* dcache_wbinv_all	*/
491129198Scognet	arm10_dcache_wbinv_range,	/* dcache_wbinv_range	*/
492129198Scognet	arm10_dcache_inv_range,		/* dcache_inv_range	*/
493129198Scognet	arm10_dcache_wb_range,		/* dcache_wb_range	*/
494129198Scognet
495129198Scognet	arm10_idcache_wbinv_all,	/* idcache_wbinv_all	*/
496129198Scognet	arm10_idcache_wbinv_range,	/* idcache_wbinv_range	*/
497129198Scognet
498129198Scognet	/* Other functions */
499129198Scognet
500129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
501129198Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
502129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
503129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
504129198Scognet
505129198Scognet	(void *)cpufunc_nullop,		/* sleep		*/
506129198Scognet
507129198Scognet	/* Soft functions */
508129198Scognet
509129198Scognet	cpufunc_null_fixup,		/* dataabt_fixup	*/
510129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
511129198Scognet
512129198Scognet	arm10_context_switch,		/* context_switch	*/
513129198Scognet
514129198Scognet	arm10_setup			/* cpu setup		*/
515129198Scognet
516129198Scognet};
517129198Scognet#endif /* CPU_ARM10 */
518129198Scognet
519129198Scognet#ifdef CPU_SA110
520129198Scognetstruct cpu_functions sa110_cpufuncs = {
521129198Scognet	/* CPU functions */
522129198Scognet
523129198Scognet	cpufunc_id,			/* id			*/
524129198Scognet	cpufunc_nullop,			/* cpwait		*/
525129198Scognet
526129198Scognet	/* MMU functions */
527129198Scognet
528129198Scognet	cpufunc_control,		/* control		*/
529129198Scognet	cpufunc_domains,		/* domain		*/
530129198Scognet	sa1_setttb,			/* setttb		*/
531129198Scognet	cpufunc_faultstatus,		/* faultstatus		*/
532129198Scognet	cpufunc_faultaddress,		/* faultaddress		*/
533129198Scognet
534129198Scognet	/* TLB functions */
535129198Scognet
536129198Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
537129198Scognet	sa1_tlb_flushID_SE,		/* tlb_flushID_SE	*/
538129198Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
539129198Scognet	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
540129198Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
541129198Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
542129198Scognet
543129198Scognet	/* Cache operations */
544129198Scognet
545129198Scognet	sa1_cache_syncI,		/* icache_sync_all	*/
546129198Scognet	sa1_cache_syncI_rng,		/* icache_sync_range	*/
547129198Scognet
548129198Scognet	sa1_cache_purgeD,		/* dcache_wbinv_all	*/
549129198Scognet	sa1_cache_purgeD_rng,		/* dcache_wbinv_range	*/
550129198Scognet/*XXX*/	sa1_cache_purgeD_rng,		/* dcache_inv_range	*/
551129198Scognet	sa1_cache_cleanD_rng,		/* dcache_wb_range	*/
552129198Scognet
553129198Scognet	sa1_cache_purgeID,		/* idcache_wbinv_all	*/
554129198Scognet	sa1_cache_purgeID_rng,		/* idcache_wbinv_range	*/
555129198Scognet
556129198Scognet	/* Other functions */
557129198Scognet
558129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
559129198Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
560129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
561129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
562129198Scognet
563129198Scognet	(void *)cpufunc_nullop,		/* sleep		*/
564129198Scognet
565129198Scognet	/* Soft functions */
566129198Scognet
567129198Scognet	cpufunc_null_fixup,		/* dataabt_fixup	*/
568129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
569129198Scognet
570129198Scognet	sa110_context_switch,		/* context_switch	*/
571129198Scognet
572129198Scognet	sa110_setup			/* cpu setup		*/
573129198Scognet};
574129198Scognet#endif	/* CPU_SA110 */
575129198Scognet
576129198Scognet#if defined(CPU_SA1100) || defined(CPU_SA1110)
577129198Scognetstruct cpu_functions sa11x0_cpufuncs = {
578129198Scognet	/* CPU functions */
579129198Scognet
580129198Scognet	cpufunc_id,			/* id			*/
581129198Scognet	cpufunc_nullop,			/* cpwait		*/
582129198Scognet
583129198Scognet	/* MMU functions */
584129198Scognet
585129198Scognet	cpufunc_control,		/* control		*/
586129198Scognet	cpufunc_domains,		/* domain		*/
587129198Scognet	sa1_setttb,			/* setttb		*/
588129198Scognet	cpufunc_faultstatus,		/* faultstatus		*/
589129198Scognet	cpufunc_faultaddress,		/* faultaddress		*/
590129198Scognet
591129198Scognet	/* TLB functions */
592129198Scognet
593129198Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
594129198Scognet	sa1_tlb_flushID_SE,		/* tlb_flushID_SE	*/
595129198Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
596129198Scognet	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
597129198Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
598129198Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
599129198Scognet
600129198Scognet	/* Cache operations */
601129198Scognet
602129198Scognet	sa1_cache_syncI,		/* icache_sync_all	*/
603129198Scognet	sa1_cache_syncI_rng,		/* icache_sync_range	*/
604129198Scognet
605129198Scognet	sa1_cache_purgeD,		/* dcache_wbinv_all	*/
606129198Scognet	sa1_cache_purgeD_rng,		/* dcache_wbinv_range	*/
607129198Scognet/*XXX*/	sa1_cache_purgeD_rng,		/* dcache_inv_range	*/
608129198Scognet	sa1_cache_cleanD_rng,		/* dcache_wb_range	*/
609129198Scognet
610129198Scognet	sa1_cache_purgeID,		/* idcache_wbinv_all	*/
611129198Scognet	sa1_cache_purgeID_rng,		/* idcache_wbinv_range	*/
612129198Scognet
613129198Scognet	/* Other functions */
614129198Scognet
615129198Scognet	sa11x0_drain_readbuf,		/* flush_prefetchbuf	*/
616129198Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
617129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
618129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
619129198Scognet
620129198Scognet	sa11x0_cpu_sleep,		/* sleep		*/
621129198Scognet
622129198Scognet	/* Soft functions */
623129198Scognet
624129198Scognet	cpufunc_null_fixup,		/* dataabt_fixup	*/
625129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
626129198Scognet
627129198Scognet	sa11x0_context_switch,		/* context_switch	*/
628129198Scognet
629129198Scognet	sa11x0_setup			/* cpu setup		*/
630129198Scognet};
631129198Scognet#endif	/* CPU_SA1100 || CPU_SA1110 */
632129198Scognet
633129198Scognet#ifdef CPU_IXP12X0
634129198Scognetstruct cpu_functions ixp12x0_cpufuncs = {
635129198Scognet	/* CPU functions */
636129198Scognet
637129198Scognet	cpufunc_id,			/* id			*/
638129198Scognet	cpufunc_nullop,			/* cpwait		*/
639129198Scognet
640129198Scognet	/* MMU functions */
641129198Scognet
642129198Scognet	cpufunc_control,		/* control		*/
643129198Scognet	cpufunc_domains,		/* domain		*/
644129198Scognet	sa1_setttb,			/* setttb		*/
645129198Scognet	cpufunc_faultstatus,		/* faultstatus		*/
646129198Scognet	cpufunc_faultaddress,		/* faultaddress		*/
647129198Scognet
648129198Scognet	/* TLB functions */
649129198Scognet
650129198Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
651129198Scognet	sa1_tlb_flushID_SE,		/* tlb_flushID_SE	*/
652129198Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
653129198Scognet	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
654129198Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
655129198Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
656129198Scognet
657129198Scognet	/* Cache operations */
658129198Scognet
659129198Scognet	sa1_cache_syncI,		/* icache_sync_all	*/
660129198Scognet	sa1_cache_syncI_rng,		/* icache_sync_range	*/
661129198Scognet
662129198Scognet	sa1_cache_purgeD,		/* dcache_wbinv_all	*/
663129198Scognet	sa1_cache_purgeD_rng,		/* dcache_wbinv_range	*/
664129198Scognet/*XXX*/	sa1_cache_purgeD_rng,		/* dcache_inv_range	*/
665129198Scognet	sa1_cache_cleanD_rng,		/* dcache_wb_range	*/
666129198Scognet
667129198Scognet	sa1_cache_purgeID,		/* idcache_wbinv_all	*/
668129198Scognet	sa1_cache_purgeID_rng,		/* idcache_wbinv_range	*/
669129198Scognet
670129198Scognet	/* Other functions */
671129198Scognet
672129198Scognet	ixp12x0_drain_readbuf,			/* flush_prefetchbuf	*/
673129198Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
674129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
675129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
676129198Scognet
677129198Scognet	(void *)cpufunc_nullop,		/* sleep		*/
678129198Scognet
679129198Scognet	/* Soft functions */
680129198Scognet
681129198Scognet	cpufunc_null_fixup,		/* dataabt_fixup	*/
682129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
683129198Scognet
684129198Scognet	ixp12x0_context_switch,		/* context_switch	*/
685129198Scognet
686129198Scognet	ixp12x0_setup			/* cpu setup		*/
687129198Scognet};
688129198Scognet#endif	/* CPU_IXP12X0 */
689129198Scognet
690129198Scognet#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
691129198Scognet    defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425)
692129198Scognetstruct cpu_functions xscale_cpufuncs = {
693129198Scognet	/* CPU functions */
694129198Scognet
695129198Scognet	cpufunc_id,			/* id			*/
696129198Scognet	xscale_cpwait,			/* cpwait		*/
697129198Scognet
698129198Scognet	/* MMU functions */
699129198Scognet
700129198Scognet	xscale_control,			/* control		*/
701129198Scognet	cpufunc_domains,		/* domain		*/
702129198Scognet	xscale_setttb,			/* setttb		*/
703129198Scognet	cpufunc_faultstatus,		/* faultstatus		*/
704129198Scognet	cpufunc_faultaddress,		/* faultaddress		*/
705129198Scognet
706129198Scognet	/* TLB functions */
707129198Scognet
708129198Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
709129198Scognet	xscale_tlb_flushID_SE,		/* tlb_flushID_SE	*/
710129198Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
711129198Scognet	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
712129198Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
713129198Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
714129198Scognet
715129198Scognet	/* Cache operations */
716129198Scognet
717129198Scognet	xscale_cache_syncI,		/* icache_sync_all	*/
718129198Scognet	xscale_cache_syncI_rng,		/* icache_sync_range	*/
719129198Scognet
720129198Scognet	xscale_cache_purgeD,		/* dcache_wbinv_all	*/
721129198Scognet	xscale_cache_purgeD_rng,	/* dcache_wbinv_range	*/
722129198Scognet	xscale_cache_flushD_rng,	/* dcache_inv_range	*/
723129198Scognet	xscale_cache_cleanD_rng,	/* dcache_wb_range	*/
724129198Scognet
725129198Scognet	xscale_cache_purgeID,		/* idcache_wbinv_all	*/
726129198Scognet	xscale_cache_purgeID_rng,	/* idcache_wbinv_range	*/
727129198Scognet
728129198Scognet	/* Other functions */
729129198Scognet
730129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
731129198Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
732129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
733129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
734129198Scognet
735129198Scognet	xscale_cpu_sleep,		/* sleep		*/
736129198Scognet
737129198Scognet	/* Soft functions */
738129198Scognet
739129198Scognet	cpufunc_null_fixup,		/* dataabt_fixup	*/
740129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
741129198Scognet
742129198Scognet	xscale_context_switch,		/* context_switch	*/
743129198Scognet
744129198Scognet	xscale_setup			/* cpu setup		*/
745129198Scognet};
746129198Scognet#endif
747129198Scognet/* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */
748129198Scognet
749129198Scognet/*
750129198Scognet * Global constants also used by locore.s
751129198Scognet */
752129198Scognet
753129198Scognetstruct cpu_functions cpufuncs;
754129198Scognetu_int cputype;
755129198Scognetu_int cpu_reset_needs_v4_MMU_disable;	/* flag used in locore.s */
756129198Scognet
757129198Scognet#if defined(CPU_ARM7TDMI) || defined(CPU_ARM8) || defined(CPU_ARM9) || \
758129198Scognet    defined (CPU_ARM10) || \
759129198Scognet    defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
760129198Scognet    defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425)
761137498Strhodesstatic void get_cachetype_cp15(void);
762129198Scognet
763129198Scognet/* Additional cache information local to this file.  Log2 of some of the
764129198Scognet   above numbers.  */
765129198Scognetstatic int	arm_dcache_l2_nsets;
766129198Scognetstatic int	arm_dcache_l2_assoc;
767129198Scognetstatic int	arm_dcache_l2_linesize;
768129198Scognet
769129198Scognetstatic void
770129198Scognetget_cachetype_cp15()
771129198Scognet{
772129198Scognet	u_int ctype, isize, dsize;
773129198Scognet	u_int multiplier;
774129198Scognet
775129198Scognet	__asm __volatile("mrc p15, 0, %0, c0, c0, 1"
776129198Scognet		: "=r" (ctype));
777129198Scognet
778129198Scognet	/*
779129198Scognet	 * ...and thus spake the ARM ARM:
780129198Scognet	 *
781129198Scognet	 * If an <opcode2> value corresponding to an unimplemented or
782129198Scognet	 * reserved ID register is encountered, the System Control
783129198Scognet	 * processor returns the value of the main ID register.
784129198Scognet	 */
785129198Scognet	if (ctype == cpufunc_id())
786129198Scognet		goto out;
787129198Scognet
788129198Scognet	if ((ctype & CPU_CT_S) == 0)
789129198Scognet		arm_pcache_unified = 1;
790129198Scognet
791129198Scognet	/*
792129198Scognet	 * If you want to know how this code works, go read the ARM ARM.
793129198Scognet	 */
794129198Scognet
795129198Scognet	arm_pcache_type = CPU_CT_CTYPE(ctype);
796129198Scognet
797129198Scognet	if (arm_pcache_unified == 0) {
798129198Scognet		isize = CPU_CT_ISIZE(ctype);
799129198Scognet		multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2;
800129198Scognet		arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3);
801129198Scognet		if (CPU_CT_xSIZE_ASSOC(isize) == 0) {
802129198Scognet			if (isize & CPU_CT_xSIZE_M)
803129198Scognet				arm_picache_line_size = 0; /* not present */
804129198Scognet			else
805129198Scognet				arm_picache_ways = 1;
806129198Scognet		} else {
807129198Scognet			arm_picache_ways = multiplier <<
808129198Scognet			    (CPU_CT_xSIZE_ASSOC(isize) - 1);
809129198Scognet		}
810129198Scognet		arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
811129198Scognet	}
812129198Scognet
813129198Scognet	dsize = CPU_CT_DSIZE(ctype);
814129198Scognet	multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
815129198Scognet	arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
816129198Scognet	if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
817129198Scognet		if (dsize & CPU_CT_xSIZE_M)
818129198Scognet			arm_pdcache_line_size = 0; /* not present */
819129198Scognet		else
820129198Scognet			arm_pdcache_ways = 1;
821129198Scognet	} else {
822129198Scognet		arm_pdcache_ways = multiplier <<
823129198Scognet		    (CPU_CT_xSIZE_ASSOC(dsize) - 1);
824129198Scognet	}
825129198Scognet	arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
826129198Scognet
827129198Scognet	arm_dcache_align = arm_pdcache_line_size;
828129198Scognet
829129198Scognet	arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2;
830129198Scognet	arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3;
831129198Scognet	arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) -
832129198Scognet	    CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize);
833129198Scognet
834129198Scognet out:
835129198Scognet	arm_dcache_align_mask = arm_dcache_align - 1;
836129198Scognet}
837129198Scognet#endif /* ARM7TDMI || ARM8 || ARM9 || XSCALE */
838129198Scognet
839129198Scognet#if defined(CPU_ARM2) || defined(CPU_ARM250) || defined(CPU_ARM3) || \
840129198Scognet    defined(CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_SA110) || \
841129198Scognet    defined(CPU_SA1100) || defined(CPU_SA1110) || defined(CPU_IXP12X0)
842129198Scognet/* Cache information for CPUs without cache type registers. */
843129198Scognetstruct cachetab {
844129198Scognet	u_int32_t ct_cpuid;
845129198Scognet	int	ct_pcache_type;
846129198Scognet	int	ct_pcache_unified;
847129198Scognet	int	ct_pdcache_size;
848129198Scognet	int	ct_pdcache_line_size;
849129198Scognet	int	ct_pdcache_ways;
850129198Scognet	int	ct_picache_size;
851129198Scognet	int	ct_picache_line_size;
852129198Scognet	int	ct_picache_ways;
853129198Scognet};
854129198Scognet
855129198Scognetstruct cachetab cachetab[] = {
856129198Scognet    /* cpuid,           cache type,       u,  dsiz, ls, wy,  isiz, ls, wy */
857129198Scognet    { CPU_ID_ARM2,      0,                1,     0,  0,  0,     0,  0,  0 },
858129198Scognet    { CPU_ID_ARM250,    0,                1,     0,  0,  0,     0,  0,  0 },
859129198Scognet    { CPU_ID_ARM3,      CPU_CT_CTYPE_WT,  1,  4096, 16, 64,     0,  0,  0 },
860129198Scognet    { CPU_ID_ARM610,	CPU_CT_CTYPE_WT,  1,  4096, 16, 64,     0,  0,  0 },
861129198Scognet    { CPU_ID_ARM710,    CPU_CT_CTYPE_WT,  1,  8192, 32,  4,     0,  0,  0 },
862129198Scognet    { CPU_ID_ARM7500,   CPU_CT_CTYPE_WT,  1,  4096, 16,  4,     0,  0,  0 },
863129198Scognet    { CPU_ID_ARM710A,   CPU_CT_CTYPE_WT,  1,  8192, 16,  4,     0,  0,  0 },
864129198Scognet    { CPU_ID_ARM7500FE, CPU_CT_CTYPE_WT,  1,  4096, 16,  4,     0,  0,  0 },
865129198Scognet    /* XXX is this type right for SA-1? */
866129198Scognet    { CPU_ID_SA110,	CPU_CT_CTYPE_WB1, 0, 16384, 32, 32, 16384, 32, 32 },
867129198Scognet    { CPU_ID_SA1100,	CPU_CT_CTYPE_WB1, 0,  8192, 32, 32, 16384, 32, 32 },
868129198Scognet    { CPU_ID_SA1110,	CPU_CT_CTYPE_WB1, 0,  8192, 32, 32, 16384, 32, 32 },
869129198Scognet    { CPU_ID_IXP1200,	CPU_CT_CTYPE_WB1, 0, 16384, 32, 32, 16384, 32, 32 }, /* XXX */
870129198Scognet    { 0, 0, 0, 0, 0, 0, 0, 0}
871129198Scognet};
872129198Scognet
873137498Strhodesstatic void get_cachetype_table(void);
874129198Scognet
875129198Scognetstatic void
876129198Scognetget_cachetype_table()
877129198Scognet{
878129198Scognet	int i;
879129198Scognet	u_int32_t cpuid = cpufunc_id();
880129198Scognet
881129198Scognet	for (i = 0; cachetab[i].ct_cpuid != 0; i++) {
882129198Scognet		if (cachetab[i].ct_cpuid == (cpuid & CPU_ID_CPU_MASK)) {
883129198Scognet			arm_pcache_type = cachetab[i].ct_pcache_type;
884129198Scognet			arm_pcache_unified = cachetab[i].ct_pcache_unified;
885129198Scognet			arm_pdcache_size = cachetab[i].ct_pdcache_size;
886129198Scognet			arm_pdcache_line_size =
887129198Scognet			    cachetab[i].ct_pdcache_line_size;
888129198Scognet			arm_pdcache_ways = cachetab[i].ct_pdcache_ways;
889129198Scognet			arm_picache_size = cachetab[i].ct_picache_size;
890129198Scognet			arm_picache_line_size =
891129198Scognet			    cachetab[i].ct_picache_line_size;
892129198Scognet			arm_picache_ways = cachetab[i].ct_picache_ways;
893129198Scognet		}
894129198Scognet	}
895129198Scognet	arm_dcache_align = arm_pdcache_line_size;
896129198Scognet
897129198Scognet	arm_dcache_align_mask = arm_dcache_align - 1;
898129198Scognet}
899129198Scognet
900129198Scognet#endif /* ARM2 || ARM250 || ARM3 || ARM6 || ARM7 || SA110 || SA1100 || SA1111 || IXP12X0 */
901129198Scognet
902129198Scognet/*
903129198Scognet * Cannot panic here as we may not have a console yet ...
904129198Scognet */
905129198Scognet
906129198Scognetint
907129198Scognetset_cpufuncs()
908129198Scognet{
909129198Scognet	cputype = cpufunc_id();
910129198Scognet	cputype &= CPU_ID_CPU_MASK;
911129198Scognet
912129198Scognet	/*
913129198Scognet	 * NOTE: cpu_do_powersave defaults to off.  If we encounter a
914129198Scognet	 * CPU type where we want to use it by default, then we set it.
915129198Scognet	 */
916129198Scognet
917129198Scognet#ifdef CPU_ARM3
918129198Scognet	if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD &&
919129198Scognet	    (cputype & 0x00000f00) == 0x00000300) {
920129198Scognet		cpufuncs = arm3_cpufuncs;
921129198Scognet		cpu_reset_needs_v4_MMU_disable = 0;
922129198Scognet		get_cachetype_table();
923129198Scognet		return 0;
924129198Scognet	}
925129198Scognet#endif	/* CPU_ARM3 */
926129198Scognet#ifdef CPU_ARM6
927129198Scognet	if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD &&
928129198Scognet	    (cputype & 0x00000f00) == 0x00000600) {
929129198Scognet		cpufuncs = arm6_cpufuncs;
930129198Scognet		cpu_reset_needs_v4_MMU_disable = 0;
931129198Scognet		get_cachetype_table();
932129198Scognet		pmap_pte_init_generic();
933129198Scognet		return 0;
934129198Scognet	}
935129198Scognet#endif	/* CPU_ARM6 */
936129198Scognet#ifdef CPU_ARM7
937129198Scognet	if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD &&
938129198Scognet	    CPU_ID_IS7(cputype) &&
939129198Scognet	    (cputype & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V3) {
940129198Scognet		cpufuncs = arm7_cpufuncs;
941129198Scognet		cpu_reset_needs_v4_MMU_disable = 0;
942129198Scognet		get_cachetype_table();
943129198Scognet		pmap_pte_init_generic();
944129198Scognet		return 0;
945129198Scognet	}
946129198Scognet#endif	/* CPU_ARM7 */
947129198Scognet#ifdef CPU_ARM7TDMI
948129198Scognet	if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD &&
949129198Scognet	    CPU_ID_IS7(cputype) &&
950129198Scognet	    (cputype & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V4T) {
951129198Scognet		cpufuncs = arm7tdmi_cpufuncs;
952129198Scognet		cpu_reset_needs_v4_MMU_disable = 0;
953129198Scognet		get_cachetype_cp15();
954129198Scognet		pmap_pte_init_generic();
955129198Scognet		return 0;
956129198Scognet	}
957129198Scognet#endif
958129198Scognet#ifdef CPU_ARM8
959129198Scognet	if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD &&
960129198Scognet	    (cputype & 0x0000f000) == 0x00008000) {
961129198Scognet		cpufuncs = arm8_cpufuncs;
962129198Scognet		cpu_reset_needs_v4_MMU_disable = 0;	/* XXX correct? */
963129198Scognet		get_cachetype_cp15();
964129198Scognet		pmap_pte_init_arm8();
965129198Scognet		return 0;
966129198Scognet	}
967129198Scognet#endif	/* CPU_ARM8 */
968129198Scognet#ifdef CPU_ARM9
969129198Scognet	if (((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD ||
970129198Scognet	     (cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_TI) &&
971129198Scognet	    (cputype & 0x0000f000) == 0x00009000) {
972129198Scognet		cpufuncs = arm9_cpufuncs;
973129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* V4 or higher */
974129198Scognet		get_cachetype_cp15();
975146605Scognet		arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize;
976146605Scognet		arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize +
977146605Scognet		    arm_dcache_l2_nsets)) - arm9_dcache_sets_inc;
978146605Scognet		arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc);
979146605Scognet		arm9_dcache_index_max = 0U - arm9_dcache_index_inc;
980137270Scognet#ifdef ARM9_CACHE_WRITE_THROUGH
981129198Scognet		pmap_pte_init_arm9();
982137270Scognet#else
983137270Scognet		pmap_pte_init_generic();
984137270Scognet#endif
985129198Scognet		return 0;
986129198Scognet	}
987129198Scognet#endif /* CPU_ARM9 */
988129198Scognet#ifdef CPU_ARM10
989129198Scognet	if (/* cputype == CPU_ID_ARM1020T || */
990129198Scognet	    cputype == CPU_ID_ARM1020E) {
991129198Scognet		/*
992129198Scognet		 * Select write-through cacheing (this isn't really an
993129198Scognet		 * option on ARM1020T).
994129198Scognet		 */
995129198Scognet		cpufuncs = arm10_cpufuncs;
996129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* V4 or higher */
997129198Scognet		get_cachetype_cp15();
998129198Scognet		arm10_dcache_sets_inc = 1U << arm_dcache_l2_linesize;
999129198Scognet		arm10_dcache_sets_max =
1000129198Scognet		    (1U << (arm_dcache_l2_linesize + arm_dcache_l2_nsets)) -
1001129198Scognet		    arm10_dcache_sets_inc;
1002129198Scognet		arm10_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc);
1003129198Scognet		arm10_dcache_index_max = 0U - arm10_dcache_index_inc;
1004129198Scognet		pmap_pte_init_generic();
1005129198Scognet		return 0;
1006129198Scognet	}
1007129198Scognet#endif /* CPU_ARM10 */
1008129198Scognet#ifdef CPU_SA110
1009129198Scognet	if (cputype == CPU_ID_SA110) {
1010129198Scognet		cpufuncs = sa110_cpufuncs;
1011129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* SA needs it */
1012129198Scognet		get_cachetype_table();
1013129198Scognet		pmap_pte_init_sa1();
1014129198Scognet		return 0;
1015129198Scognet	}
1016129198Scognet#endif	/* CPU_SA110 */
1017129198Scognet#ifdef CPU_SA1100
1018129198Scognet	if (cputype == CPU_ID_SA1100) {
1019129198Scognet		cpufuncs = sa11x0_cpufuncs;
1020129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* SA needs it	*/
1021129198Scognet		get_cachetype_table();
1022129198Scognet		pmap_pte_init_sa1();
1023129198Scognet		/* Use powersave on this CPU. */
1024129198Scognet		cpu_do_powersave = 1;
1025129198Scognet
1026129198Scognet		return 0;
1027129198Scognet	}
1028129198Scognet#endif	/* CPU_SA1100 */
1029129198Scognet#ifdef CPU_SA1110
1030129198Scognet	if (cputype == CPU_ID_SA1110) {
1031129198Scognet		cpufuncs = sa11x0_cpufuncs;
1032129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* SA needs it	*/
1033129198Scognet		get_cachetype_table();
1034129198Scognet		pmap_pte_init_sa1();
1035129198Scognet		/* Use powersave on this CPU. */
1036129198Scognet		cpu_do_powersave = 1;
1037129198Scognet
1038129198Scognet		return 0;
1039129198Scognet	}
1040129198Scognet#endif	/* CPU_SA1110 */
1041129198Scognet#ifdef CPU_IXP12X0
1042129198Scognet        if (cputype == CPU_ID_IXP1200) {
1043129198Scognet                cpufuncs = ixp12x0_cpufuncs;
1044129198Scognet                cpu_reset_needs_v4_MMU_disable = 1;
1045129198Scognet                get_cachetype_table();
1046129198Scognet                pmap_pte_init_sa1();
1047129198Scognet                return 0;
1048129198Scognet        }
1049129198Scognet#endif  /* CPU_IXP12X0 */
1050129198Scognet#ifdef CPU_XSCALE_80200
1051129198Scognet	if (cputype == CPU_ID_80200) {
1052129198Scognet		int rev = cpufunc_id() & CPU_ID_REVISION_MASK;
1053129198Scognet
1054129198Scognet		i80200_icu_init();
1055129198Scognet
1056129198Scognet		/*
1057129198Scognet		 * Reset the Performance Monitoring Unit to a
1058129198Scognet		 * pristine state:
1059129198Scognet		 *	- CCNT, PMN0, PMN1 reset to 0
1060129198Scognet		 *	- overflow indications cleared
1061129198Scognet		 *	- all counters disabled
1062129198Scognet		 */
1063129198Scognet		__asm __volatile("mcr p14, 0, %0, c0, c0, 0"
1064129198Scognet			:
1065129198Scognet			: "r" (PMNC_P|PMNC_C|PMNC_PMN0_IF|PMNC_PMN1_IF|
1066129198Scognet			       PMNC_CC_IF));
1067129198Scognet
1068129198Scognet#if defined(XSCALE_CCLKCFG)
1069129198Scognet		/*
1070129198Scognet		 * Crank CCLKCFG to maximum legal value.
1071129198Scognet		 */
1072129198Scognet		__asm __volatile ("mcr p14, 0, %0, c6, c0, 0"
1073129198Scognet			:
1074129198Scognet			: "r" (XSCALE_CCLKCFG));
1075129198Scognet#endif
1076129198Scognet
1077129198Scognet		/*
1078129198Scognet		 * XXX Disable ECC in the Bus Controller Unit; we
1079129198Scognet		 * don't really support it, yet.  Clear any pending
1080129198Scognet		 * error indications.
1081129198Scognet		 */
1082129198Scognet		__asm __volatile("mcr p13, 0, %0, c0, c1, 0"
1083129198Scognet			:
1084129198Scognet			: "r" (BCUCTL_E0|BCUCTL_E1|BCUCTL_EV));
1085129198Scognet
1086129198Scognet		cpufuncs = xscale_cpufuncs;
1087129198Scognet#if defined(PERFCTRS)
1088129198Scognet		xscale_pmu_init();
1089129198Scognet#endif
1090129198Scognet
1091129198Scognet		/*
1092129198Scognet		 * i80200 errata: Step-A0 and A1 have a bug where
1093129198Scognet		 * D$ dirty bits are not cleared on "invalidate by
1094129198Scognet		 * address".
1095129198Scognet		 *
1096129198Scognet		 * Workaround: Clean cache line before invalidating.
1097129198Scognet		 */
1098129198Scognet		if (rev == 0 || rev == 1)
1099129198Scognet			cpufuncs.cf_dcache_inv_range = xscale_cache_purgeD_rng;
1100129198Scognet
1101129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
1102129198Scognet		get_cachetype_cp15();
1103129198Scognet		pmap_pte_init_xscale();
1104129198Scognet		return 0;
1105129198Scognet	}
1106129198Scognet#endif /* CPU_XSCALE_80200 */
1107129198Scognet#ifdef CPU_XSCALE_80321
1108129198Scognet	if (cputype == CPU_ID_80321_400 || cputype == CPU_ID_80321_600 ||
1109129198Scognet	    cputype == CPU_ID_80321_400_B0 || cputype == CPU_ID_80321_600_B0) {
1110129198Scognet
1111129198Scognet		/*
1112129198Scognet		 * Reset the Performance Monitoring Unit to a
1113129198Scognet		 * pristine state:
1114129198Scognet		 *	- CCNT, PMN0, PMN1 reset to 0
1115129198Scognet		 *	- overflow indications cleared
1116129198Scognet		 *	- all counters disabled
1117129198Scognet		 */
1118129198Scognet		__asm __volatile("mcr p14, 0, %0, c0, c0, 0"
1119129198Scognet			:
1120129198Scognet			: "r" (PMNC_P|PMNC_C|PMNC_PMN0_IF|PMNC_PMN1_IF|
1121129198Scognet			       PMNC_CC_IF));
1122129198Scognet
1123129198Scognet		cpufuncs = xscale_cpufuncs;
1124129198Scognet#if defined(PERFCTRS)
1125129198Scognet		xscale_pmu_init();
1126129198Scognet#endif
1127129198Scognet
1128129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
1129129198Scognet		get_cachetype_cp15();
1130129198Scognet		pmap_pte_init_xscale();
1131129198Scognet		return 0;
1132129198Scognet	}
1133129198Scognet#endif /* CPU_XSCALE_80321 */
1134129198Scognet#ifdef CPU_XSCALE_PXA2X0
1135129198Scognet	/* ignore core revision to test PXA2xx CPUs */
1136129198Scognet	if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA250 ||
1137129198Scognet	    (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA210) {
1138129198Scognet
1139129198Scognet		cpufuncs = xscale_cpufuncs;
1140129198Scognet#if defined(PERFCTRS)
1141129198Scognet		xscale_pmu_init();
1142129198Scognet#endif
1143129198Scognet
1144129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
1145129198Scognet		get_cachetype_cp15();
1146129198Scognet		pmap_pte_init_xscale();
1147129198Scognet
1148129198Scognet		/* Use powersave on this CPU. */
1149129198Scognet		cpu_do_powersave = 1;
1150129198Scognet
1151129198Scognet		return 0;
1152129198Scognet	}
1153129198Scognet#endif /* CPU_XSCALE_PXA2X0 */
1154129198Scognet#ifdef CPU_XSCALE_IXP425
1155129198Scognet	if (cputype == CPU_ID_IXP425_533 || cputype == CPU_ID_IXP425_400 ||
1156129198Scognet            cputype == CPU_ID_IXP425_266) {
1157129198Scognet		ixp425_icu_init();
1158129198Scognet
1159129198Scognet		cpufuncs = xscale_cpufuncs;
1160129198Scognet#if defined(PERFCTRS)
1161129198Scognet		xscale_pmu_init();
1162129198Scognet#endif
1163129198Scognet
1164129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
1165129198Scognet		get_cachetype_cp15();
1166129198Scognet		pmap_pte_init_xscale();
1167129198Scognet
1168129198Scognet		return 0;
1169129198Scognet	}
1170129198Scognet#endif /* CPU_XSCALE_IXP425 */
1171129198Scognet	/*
1172129198Scognet	 * Bzzzz. And the answer was ...
1173129198Scognet	 */
1174129198Scognet	panic("No support for this CPU type (%08x) in kernel", cputype);
1175129198Scognet	return(ARCHITECTURE_NOT_PRESENT);
1176129198Scognet}
1177129198Scognet
1178129198Scognet/*
1179129198Scognet * Fixup routines for data and prefetch aborts.
1180129198Scognet *
1181129198Scognet * Several compile time symbols are used
1182129198Scognet *
1183129198Scognet * DEBUG_FAULT_CORRECTION - Print debugging information during the
1184129198Scognet * correction of registers after a fault.
1185129198Scognet * ARM6_LATE_ABORT - ARM6 supports both early and late aborts
1186129198Scognet * when defined should use late aborts
1187129198Scognet */
1188129198Scognet
1189129198Scognet
1190129198Scognet/*
1191129198Scognet * Null abort fixup routine.
1192129198Scognet * For use when no fixup is required.
1193129198Scognet */
1194129198Scognetint
1195129198Scognetcpufunc_null_fixup(arg)
1196129198Scognet	void *arg;
1197129198Scognet{
1198129198Scognet	return(ABORT_FIXUP_OK);
1199129198Scognet}
1200129198Scognet
1201129198Scognet
1202129198Scognet#if defined(CPU_ARM2) || defined(CPU_ARM250) || defined(CPU_ARM3) || \
1203129198Scognet    defined(CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI)
1204129198Scognet
1205129198Scognet#ifdef DEBUG_FAULT_CORRECTION
1206129198Scognet#define DFC_PRINTF(x)		printf x
1207129198Scognet#define DFC_DISASSEMBLE(x)	disassemble(x)
1208129198Scognet#else
1209129198Scognet#define DFC_PRINTF(x)		/* nothing */
1210129198Scognet#define DFC_DISASSEMBLE(x)	/* nothing */
1211129198Scognet#endif
1212129198Scognet
1213129198Scognet/*
1214129198Scognet * "Early" data abort fixup.
1215129198Scognet *
1216129198Scognet * For ARM2, ARM2as, ARM3 and ARM6 (in early-abort mode).  Also used
1217129198Scognet * indirectly by ARM6 (in late-abort mode) and ARM7[TDMI].
1218129198Scognet *
1219129198Scognet * In early aborts, we may have to fix up LDM, STM, LDC and STC.
1220129198Scognet */
1221129198Scognetint
1222129198Scognetearly_abort_fixup(arg)
1223129198Scognet	void *arg;
1224129198Scognet{
1225129198Scognet	trapframe_t *frame = arg;
1226129198Scognet	u_int fault_pc;
1227129198Scognet	u_int fault_instruction;
1228129198Scognet	int saved_lr = 0;
1229129198Scognet
1230129198Scognet	if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
1231129198Scognet
1232129198Scognet		/* Ok an abort in SVC mode */
1233129198Scognet
1234129198Scognet		/*
1235129198Scognet		 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage
1236129198Scognet		 * as the fault happened in svc mode but we need it in the
1237129198Scognet		 * usr slot so we can treat the registers as an array of ints
1238129198Scognet		 * during fixing.
1239129198Scognet		 * NOTE: This PC is in the position but writeback is not
1240129198Scognet		 * allowed on r15.
1241129198Scognet		 * Doing it like this is more efficient than trapping this
1242129198Scognet		 * case in all possible locations in the following fixup code.
1243129198Scognet		 */
1244129198Scognet
1245129198Scognet		saved_lr = frame->tf_usr_lr;
1246129198Scognet		frame->tf_usr_lr = frame->tf_svc_lr;
1247129198Scognet
1248129198Scognet		/*
1249129198Scognet		 * Note the trapframe does not have the SVC r13 so a fault
1250129198Scognet		 * from an instruction with writeback to r13 in SVC mode is
1251129198Scognet		 * not allowed. This should not happen as the kstack is
1252129198Scognet		 * always valid.
1253129198Scognet		 */
1254129198Scognet	}
1255129198Scognet
1256129198Scognet	/* Get fault address and status from the CPU */
1257129198Scognet
1258129198Scognet	fault_pc = frame->tf_pc;
1259129198Scognet	fault_instruction = *((volatile unsigned int *)fault_pc);
1260129198Scognet
1261129198Scognet	/* Decode the fault instruction and fix the registers as needed */
1262129198Scognet
1263129198Scognet	if ((fault_instruction & 0x0e000000) == 0x08000000) {
1264129198Scognet		int base;
1265129198Scognet		int loop;
1266129198Scognet		int count;
1267129198Scognet		int *registers = &frame->tf_r0;
1268129198Scognet
1269129198Scognet		DFC_PRINTF(("LDM/STM\n"));
1270129198Scognet		DFC_DISASSEMBLE(fault_pc);
1271129198Scognet		if (fault_instruction & (1 << 21)) {
1272129198Scognet			DFC_PRINTF(("This instruction must be corrected\n"));
1273129198Scognet			base = (fault_instruction >> 16) & 0x0f;
1274129198Scognet			if (base == 15)
1275129198Scognet				return ABORT_FIXUP_FAILED;
1276129198Scognet			/* Count registers transferred */
1277129198Scognet			count = 0;
1278129198Scognet			for (loop = 0; loop < 16; ++loop) {
1279129198Scognet				if (fault_instruction & (1<<loop))
1280129198Scognet					++count;
1281129198Scognet			}
1282129198Scognet			DFC_PRINTF(("%d registers used\n", count));
1283129198Scognet			DFC_PRINTF(("Corrected r%d by %d bytes ",
1284129198Scognet				       base, count * 4));
1285129198Scognet			if (fault_instruction & (1 << 23)) {
1286129198Scognet				DFC_PRINTF(("down\n"));
1287129198Scognet				registers[base] -= count * 4;
1288129198Scognet			} else {
1289129198Scognet				DFC_PRINTF(("up\n"));
1290129198Scognet				registers[base] += count * 4;
1291129198Scognet			}
1292129198Scognet		}
1293129198Scognet	} else if ((fault_instruction & 0x0e000000) == 0x0c000000) {
1294129198Scognet		int base;
1295129198Scognet		int offset;
1296129198Scognet		int *registers = &frame->tf_r0;
1297129198Scognet
1298129198Scognet		/* REGISTER CORRECTION IS REQUIRED FOR THESE INSTRUCTIONS */
1299129198Scognet
1300129198Scognet		DFC_DISASSEMBLE(fault_pc);
1301129198Scognet
1302129198Scognet		/* Only need to fix registers if write back is turned on */
1303129198Scognet
1304129198Scognet		if ((fault_instruction & (1 << 21)) != 0) {
1305129198Scognet			base = (fault_instruction >> 16) & 0x0f;
1306129198Scognet			if (base == 13 &&
1307129198Scognet			    (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE)
1308129198Scognet				return ABORT_FIXUP_FAILED;
1309129198Scognet			if (base == 15)
1310129198Scognet				return ABORT_FIXUP_FAILED;
1311129198Scognet
1312129198Scognet			offset = (fault_instruction & 0xff) << 2;
1313129198Scognet			DFC_PRINTF(("r%d=%08x\n", base, registers[base]));
1314129198Scognet			if ((fault_instruction & (1 << 23)) != 0)
1315129198Scognet				offset = -offset;
1316129198Scognet			registers[base] += offset;
1317129198Scognet			DFC_PRINTF(("r%d=%08x\n", base, registers[base]));
1318129198Scognet		}
1319129198Scognet	} else if ((fault_instruction & 0x0e000000) == 0x0c000000)
1320129198Scognet		return ABORT_FIXUP_FAILED;
1321129198Scognet
1322129198Scognet	if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
1323129198Scognet
1324129198Scognet		/* Ok an abort in SVC mode */
1325129198Scognet
1326129198Scognet		/*
1327129198Scognet		 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage
1328129198Scognet		 * as the fault happened in svc mode but we need it in the
1329129198Scognet		 * usr slot so we can treat the registers as an array of ints
1330129198Scognet		 * during fixing.
1331129198Scognet		 * NOTE: This PC is in the position but writeback is not
1332129198Scognet		 * allowed on r15.
1333129198Scognet		 * Doing it like this is more efficient than trapping this
1334129198Scognet		 * case in all possible locations in the prior fixup code.
1335129198Scognet		 */
1336129198Scognet
1337129198Scognet		frame->tf_svc_lr = frame->tf_usr_lr;
1338129198Scognet		frame->tf_usr_lr = saved_lr;
1339129198Scognet
1340129198Scognet		/*
1341129198Scognet		 * Note the trapframe does not have the SVC r13 so a fault
1342129198Scognet		 * from an instruction with writeback to r13 in SVC mode is
1343129198Scognet		 * not allowed. This should not happen as the kstack is
1344129198Scognet		 * always valid.
1345129198Scognet		 */
1346129198Scognet	}
1347129198Scognet
1348129198Scognet	return(ABORT_FIXUP_OK);
1349129198Scognet}
1350129198Scognet#endif	/* CPU_ARM2/250/3/6/7 */
1351129198Scognet
1352129198Scognet
1353129198Scognet#if (defined(CPU_ARM6) && defined(ARM6_LATE_ABORT)) || defined(CPU_ARM7) || \
1354129198Scognet	defined(CPU_ARM7TDMI)
1355129198Scognet/*
1356129198Scognet * "Late" (base updated) data abort fixup
1357129198Scognet *
1358129198Scognet * For ARM6 (in late-abort mode) and ARM7.
1359129198Scognet *
1360129198Scognet * In this model, all data-transfer instructions need fixing up.  We defer
1361129198Scognet * LDM, STM, LDC and STC fixup to the early-abort handler.
1362129198Scognet */
1363129198Scognetint
1364129198Scognetlate_abort_fixup(arg)
1365129198Scognet	void *arg;
1366129198Scognet{
1367129198Scognet	trapframe_t *frame = arg;
1368129198Scognet	u_int fault_pc;
1369129198Scognet	u_int fault_instruction;
1370129198Scognet	int saved_lr = 0;
1371129198Scognet
1372129198Scognet	if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
1373129198Scognet
1374129198Scognet		/* Ok an abort in SVC mode */
1375129198Scognet
1376129198Scognet		/*
1377129198Scognet		 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage
1378129198Scognet		 * as the fault happened in svc mode but we need it in the
1379129198Scognet		 * usr slot so we can treat the registers as an array of ints
1380129198Scognet		 * during fixing.
1381129198Scognet		 * NOTE: This PC is in the position but writeback is not
1382129198Scognet		 * allowed on r15.
1383129198Scognet		 * Doing it like this is more efficient than trapping this
1384129198Scognet		 * case in all possible locations in the following fixup code.
1385129198Scognet		 */
1386129198Scognet
1387129198Scognet		saved_lr = frame->tf_usr_lr;
1388129198Scognet		frame->tf_usr_lr = frame->tf_svc_lr;
1389129198Scognet
1390129198Scognet		/*
1391129198Scognet		 * Note the trapframe does not have the SVC r13 so a fault
1392129198Scognet		 * from an instruction with writeback to r13 in SVC mode is
1393129198Scognet		 * not allowed. This should not happen as the kstack is
1394129198Scognet		 * always valid.
1395129198Scognet		 */
1396129198Scognet	}
1397129198Scognet
1398129198Scognet	/* Get fault address and status from the CPU */
1399129198Scognet
1400129198Scognet	fault_pc = frame->tf_pc;
1401129198Scognet	fault_instruction = *((volatile unsigned int *)fault_pc);
1402129198Scognet
1403129198Scognet	/* Decode the fault instruction and fix the registers as needed */
1404129198Scognet
1405129198Scognet	/* Was is a swap instruction ? */
1406129198Scognet
1407129198Scognet	if ((fault_instruction & 0x0fb00ff0) == 0x01000090) {
1408129198Scognet		DFC_DISASSEMBLE(fault_pc);
1409129198Scognet	} else if ((fault_instruction & 0x0c000000) == 0x04000000) {
1410129198Scognet
1411129198Scognet		/* Was is a ldr/str instruction */
1412129198Scognet		/* This is for late abort only */
1413129198Scognet
1414129198Scognet		int base;
1415129198Scognet		int offset;
1416129198Scognet		int *registers = &frame->tf_r0;
1417129198Scognet
1418129198Scognet		DFC_DISASSEMBLE(fault_pc);
1419129198Scognet
1420129198Scognet		/* This is for late abort only */
1421129198Scognet
1422129198Scognet		if ((fault_instruction & (1 << 24)) == 0
1423129198Scognet		    || (fault_instruction & (1 << 21)) != 0) {
1424129198Scognet			/* postindexed ldr/str with no writeback */
1425129198Scognet
1426129198Scognet			base = (fault_instruction >> 16) & 0x0f;
1427129198Scognet			if (base == 13 &&
1428129198Scognet			    (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE)
1429129198Scognet				return ABORT_FIXUP_FAILED;
1430129198Scognet			if (base == 15)
1431129198Scognet				return ABORT_FIXUP_FAILED;
1432129198Scognet			DFC_PRINTF(("late abt fix: r%d=%08x : ",
1433129198Scognet				       base, registers[base]));
1434129198Scognet			if ((fault_instruction & (1 << 25)) == 0) {
1435129198Scognet				/* Immediate offset - easy */
1436129198Scognet
1437129198Scognet				offset = fault_instruction & 0xfff;
1438129198Scognet				if ((fault_instruction & (1 << 23)))
1439129198Scognet					offset = -offset;
1440129198Scognet				registers[base] += offset;
1441129198Scognet				DFC_PRINTF(("imm=%08x ", offset));
1442129198Scognet			} else {
1443129198Scognet				/* offset is a shifted register */
1444129198Scognet				int shift;
1445129198Scognet
1446129198Scognet				offset = fault_instruction & 0x0f;
1447129198Scognet				if (offset == base)
1448129198Scognet					return ABORT_FIXUP_FAILED;
1449129198Scognet
1450129198Scognet				/*
1451129198Scognet				 * Register offset - hard we have to
1452129198Scognet				 * cope with shifts !
1453129198Scognet				 */
1454129198Scognet				offset = registers[offset];
1455129198Scognet
1456129198Scognet				if ((fault_instruction & (1 << 4)) == 0)
1457129198Scognet					/* shift with amount */
1458129198Scognet					shift = (fault_instruction >> 7) & 0x1f;
1459129198Scognet				else {
1460129198Scognet					/* shift with register */
1461129198Scognet					if ((fault_instruction & (1 << 7)) != 0)
1462129198Scognet						/* undefined for now so bail out */
1463129198Scognet						return ABORT_FIXUP_FAILED;
1464129198Scognet					shift = ((fault_instruction >> 8) & 0xf);
1465129198Scognet					if (base == shift)
1466129198Scognet						return ABORT_FIXUP_FAILED;
1467129198Scognet					DFC_PRINTF(("shift reg=%d ", shift));
1468129198Scognet					shift = registers[shift];
1469129198Scognet				}
1470129198Scognet				DFC_PRINTF(("shift=%08x ", shift));
1471129198Scognet				switch (((fault_instruction >> 5) & 0x3)) {
1472129198Scognet				case 0 : /* Logical left */
1473129198Scognet					offset = (int)(((u_int)offset) << shift);
1474129198Scognet					break;
1475129198Scognet				case 1 : /* Logical Right */
1476129198Scognet					if (shift == 0) shift = 32;
1477129198Scognet					offset = (int)(((u_int)offset) >> shift);
1478129198Scognet					break;
1479129198Scognet				case 2 : /* Arithmetic Right */
1480129198Scognet					if (shift == 0) shift = 32;
1481129198Scognet					offset = (int)(((int)offset) >> shift);
1482129198Scognet					break;
1483129198Scognet				case 3 : /* Rotate right (rol or rxx) */
1484129198Scognet					return ABORT_FIXUP_FAILED;
1485129198Scognet					break;
1486129198Scognet				}
1487129198Scognet
1488129198Scognet				DFC_PRINTF(("abt: fixed LDR/STR with "
1489129198Scognet					       "register offset\n"));
1490129198Scognet				if ((fault_instruction & (1 << 23)))
1491129198Scognet					offset = -offset;
1492129198Scognet				DFC_PRINTF(("offset=%08x ", offset));
1493129198Scognet				registers[base] += offset;
1494129198Scognet			}
1495129198Scognet			DFC_PRINTF(("r%d=%08x\n", base, registers[base]));
1496129198Scognet		}
1497129198Scognet	}
1498129198Scognet
1499129198Scognet	if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
1500129198Scognet
1501129198Scognet		/* Ok an abort in SVC mode */
1502129198Scognet
1503129198Scognet		/*
1504129198Scognet		 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage
1505129198Scognet		 * as the fault happened in svc mode but we need it in the
1506129198Scognet		 * usr slot so we can treat the registers as an array of ints
1507129198Scognet		 * during fixing.
1508129198Scognet		 * NOTE: This PC is in the position but writeback is not
1509129198Scognet		 * allowed on r15.
1510129198Scognet		 * Doing it like this is more efficient than trapping this
1511129198Scognet		 * case in all possible locations in the prior fixup code.
1512129198Scognet		 */
1513129198Scognet
1514129198Scognet		frame->tf_svc_lr = frame->tf_usr_lr;
1515129198Scognet		frame->tf_usr_lr = saved_lr;
1516129198Scognet
1517129198Scognet		/*
1518129198Scognet		 * Note the trapframe does not have the SVC r13 so a fault
1519129198Scognet		 * from an instruction with writeback to r13 in SVC mode is
1520129198Scognet		 * not allowed. This should not happen as the kstack is
1521129198Scognet		 * always valid.
1522129198Scognet		 */
1523129198Scognet	}
1524129198Scognet
1525129198Scognet	/*
1526129198Scognet	 * Now let the early-abort fixup routine have a go, in case it
1527129198Scognet	 * was an LDM, STM, LDC or STC that faulted.
1528129198Scognet	 */
1529129198Scognet
1530129198Scognet	return early_abort_fixup(arg);
1531129198Scognet}
1532129198Scognet#endif	/* CPU_ARM6(LATE)/7/7TDMI */
1533129198Scognet
1534129198Scognet/*
1535129198Scognet * CPU Setup code
1536129198Scognet */
1537129198Scognet
1538129198Scognet#if defined(CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI) || \
1539129198Scognet	defined(CPU_ARM8) || defined (CPU_ARM9) || defined(CPU_SA110) || \
1540129198Scognet	defined(CPU_SA1100) || defined(CPU_SA1110) || \
1541129198Scognet	defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
1542129198Scognet	defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425)
1543129198Scognet
1544129198Scognet#define IGN	0
1545129198Scognet#define OR	1
1546129198Scognet#define BIC	2
1547129198Scognet
1548129198Scognetstruct cpu_option {
1549129198Scognet	char	*co_name;
1550129198Scognet	int	co_falseop;
1551129198Scognet	int	co_trueop;
1552129198Scognet	int	co_value;
1553129198Scognet};
1554129198Scognet
1555137498Strhodesstatic u_int parse_cpu_options(char *, struct cpu_option *, u_int);
1556129198Scognet
1557129198Scognetstatic u_int
1558129198Scognetparse_cpu_options(args, optlist, cpuctrl)
1559129198Scognet	char *args;
1560129198Scognet	struct cpu_option *optlist;
1561129198Scognet	u_int cpuctrl;
1562129198Scognet{
1563129198Scognet	int integer;
1564129198Scognet
1565129198Scognet	if (args == NULL)
1566129198Scognet		return(cpuctrl);
1567129198Scognet
1568129198Scognet	while (optlist->co_name) {
1569129198Scognet		if (get_bootconf_option(args, optlist->co_name,
1570129198Scognet		    BOOTOPT_TYPE_BOOLEAN, &integer)) {
1571129198Scognet			if (integer) {
1572129198Scognet				if (optlist->co_trueop == OR)
1573129198Scognet					cpuctrl |= optlist->co_value;
1574129198Scognet				else if (optlist->co_trueop == BIC)
1575129198Scognet					cpuctrl &= ~optlist->co_value;
1576129198Scognet			} else {
1577129198Scognet				if (optlist->co_falseop == OR)
1578129198Scognet					cpuctrl |= optlist->co_value;
1579129198Scognet				else if (optlist->co_falseop == BIC)
1580129198Scognet					cpuctrl &= ~optlist->co_value;
1581129198Scognet			}
1582129198Scognet		}
1583129198Scognet		++optlist;
1584129198Scognet	}
1585129198Scognet	return(cpuctrl);
1586129198Scognet}
1587129198Scognet#endif /* CPU_ARM6 || CPU_ARM7 || CPU_ARM7TDMI || CPU_ARM8 || CPU_SA110 */
1588129198Scognet
1589129198Scognet#if defined (CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI) \
1590129198Scognet	|| defined(CPU_ARM8)
1591129198Scognetstruct cpu_option arm678_options[] = {
1592129198Scognet#ifdef COMPAT_12
1593129198Scognet	{ "nocache",		IGN, BIC, CPU_CONTROL_IDC_ENABLE },
1594129198Scognet	{ "nowritebuf",		IGN, BIC, CPU_CONTROL_WBUF_ENABLE },
1595129198Scognet#endif	/* COMPAT_12 */
1596129198Scognet	{ "cpu.cache",		BIC, OR,  CPU_CONTROL_IDC_ENABLE },
1597129198Scognet	{ "cpu.nocache",	OR,  BIC, CPU_CONTROL_IDC_ENABLE },
1598129198Scognet	{ "cpu.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1599129198Scognet	{ "cpu.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1600129198Scognet	{ NULL,			IGN, IGN, 0 }
1601129198Scognet};
1602129198Scognet
1603129198Scognet#endif	/* CPU_ARM6 || CPU_ARM7 || CPU_ARM7TDMI || CPU_ARM8 */
1604129198Scognet
1605129198Scognet#ifdef CPU_ARM6
1606129198Scognetstruct cpu_option arm6_options[] = {
1607129198Scognet	{ "arm6.cache",		BIC, OR,  CPU_CONTROL_IDC_ENABLE },
1608129198Scognet	{ "arm6.nocache",	OR,  BIC, CPU_CONTROL_IDC_ENABLE },
1609129198Scognet	{ "arm6.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1610129198Scognet	{ "arm6.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1611129198Scognet	{ NULL,			IGN, IGN, 0 }
1612129198Scognet};
1613129198Scognet
1614129198Scognetvoid
1615129198Scognetarm6_setup(args)
1616129198Scognet	char *args;
1617129198Scognet{
1618129198Scognet	int cpuctrl, cpuctrlmask;
1619129198Scognet
1620129198Scognet	/* Set up default control registers bits */
1621129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1622129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1623129198Scognet		 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE;
1624129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1625129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1626129198Scognet		 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE
1627129198Scognet		 | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_BEND_ENABLE
1628129198Scognet		 | CPU_CONTROL_AFLT_ENABLE;
1629129198Scognet
1630129198Scognet#ifdef ARM6_LATE_ABORT
1631129198Scognet	cpuctrl |= CPU_CONTROL_LABT_ENABLE;
1632129198Scognet#endif	/* ARM6_LATE_ABORT */
1633129198Scognet
1634129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1635129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1636129198Scognet#endif
1637129198Scognet
1638129198Scognet	cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl);
1639129198Scognet	cpuctrl = parse_cpu_options(args, arm6_options, cpuctrl);
1640129198Scognet
1641129198Scognet#ifdef __ARMEB__
1642129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1643129198Scognet#endif
1644129198Scognet
1645129198Scognet	/* Clear out the cache */
1646129198Scognet	cpu_idcache_wbinv_all();
1647129198Scognet
1648129198Scognet	/* Set the control register */
1649129198Scognet	ctrl = cpuctrl;
1650129198Scognet	cpu_control(0xffffffff, cpuctrl);
1651129198Scognet}
1652129198Scognet#endif	/* CPU_ARM6 */
1653129198Scognet
1654129198Scognet#ifdef CPU_ARM7
1655129198Scognetstruct cpu_option arm7_options[] = {
1656129198Scognet	{ "arm7.cache",		BIC, OR,  CPU_CONTROL_IDC_ENABLE },
1657129198Scognet	{ "arm7.nocache",	OR,  BIC, CPU_CONTROL_IDC_ENABLE },
1658129198Scognet	{ "arm7.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1659129198Scognet	{ "arm7.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1660129198Scognet#ifdef COMPAT_12
1661129198Scognet	{ "fpaclk2",		BIC, OR,  CPU_CONTROL_CPCLK },
1662129198Scognet#endif	/* COMPAT_12 */
1663129198Scognet	{ "arm700.fpaclk",	BIC, OR,  CPU_CONTROL_CPCLK },
1664129198Scognet	{ NULL,			IGN, IGN, 0 }
1665129198Scognet};
1666129198Scognet
1667129198Scognetvoid
1668129198Scognetarm7_setup(args)
1669129198Scognet	char *args;
1670129198Scognet{
1671129198Scognet	int cpuctrl, cpuctrlmask;
1672129198Scognet
1673129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1674129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1675129198Scognet		 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE;
1676129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1677129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1678129198Scognet		 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE
1679129198Scognet		 | CPU_CONTROL_CPCLK | CPU_CONTROL_LABT_ENABLE
1680129198Scognet		 | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_BEND_ENABLE
1681129198Scognet		 | CPU_CONTROL_AFLT_ENABLE;
1682129198Scognet
1683129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1684129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1685129198Scognet#endif
1686129198Scognet
1687129198Scognet	cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl);
1688129198Scognet	cpuctrl = parse_cpu_options(args, arm7_options, cpuctrl);
1689129198Scognet
1690129198Scognet#ifdef __ARMEB__
1691129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1692129198Scognet#endif
1693129198Scognet
1694129198Scognet	/* Clear out the cache */
1695129198Scognet	cpu_idcache_wbinv_all();
1696129198Scognet
1697129198Scognet	/* Set the control register */
1698129198Scognet	ctrl = cpuctrl;
1699129198Scognet	cpu_control(0xffffffff, cpuctrl);
1700129198Scognet}
1701129198Scognet#endif	/* CPU_ARM7 */
1702129198Scognet
1703129198Scognet#ifdef CPU_ARM7TDMI
1704129198Scognetstruct cpu_option arm7tdmi_options[] = {
1705129198Scognet	{ "arm7.cache",		BIC, OR,  CPU_CONTROL_IDC_ENABLE },
1706129198Scognet	{ "arm7.nocache",	OR,  BIC, CPU_CONTROL_IDC_ENABLE },
1707129198Scognet	{ "arm7.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1708129198Scognet	{ "arm7.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1709129198Scognet#ifdef COMPAT_12
1710129198Scognet	{ "fpaclk2",		BIC, OR,  CPU_CONTROL_CPCLK },
1711129198Scognet#endif	/* COMPAT_12 */
1712129198Scognet	{ "arm700.fpaclk",	BIC, OR,  CPU_CONTROL_CPCLK },
1713129198Scognet	{ NULL,			IGN, IGN, 0 }
1714129198Scognet};
1715129198Scognet
1716129198Scognetvoid
1717129198Scognetarm7tdmi_setup(args)
1718129198Scognet	char *args;
1719129198Scognet{
1720129198Scognet	int cpuctrl;
1721129198Scognet
1722129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1723129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1724129198Scognet		 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE;
1725129198Scognet
1726129198Scognet	cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl);
1727129198Scognet	cpuctrl = parse_cpu_options(args, arm7tdmi_options, cpuctrl);
1728129198Scognet
1729129198Scognet#ifdef __ARMEB__
1730129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1731129198Scognet#endif
1732129198Scognet
1733129198Scognet	/* Clear out the cache */
1734129198Scognet	cpu_idcache_wbinv_all();
1735129198Scognet
1736129198Scognet	/* Set the control register */
1737129198Scognet	ctrl = cpuctrl;
1738129198Scognet	cpu_control(0xffffffff, cpuctrl);
1739129198Scognet}
1740129198Scognet#endif	/* CPU_ARM7TDMI */
1741129198Scognet
1742129198Scognet#ifdef CPU_ARM8
1743129198Scognetstruct cpu_option arm8_options[] = {
1744129198Scognet	{ "arm8.cache",		BIC, OR,  CPU_CONTROL_IDC_ENABLE },
1745129198Scognet	{ "arm8.nocache",	OR,  BIC, CPU_CONTROL_IDC_ENABLE },
1746129198Scognet	{ "arm8.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1747129198Scognet	{ "arm8.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1748129198Scognet#ifdef COMPAT_12
1749129198Scognet	{ "branchpredict", 	BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
1750129198Scognet#endif	/* COMPAT_12 */
1751129198Scognet	{ "cpu.branchpredict", 	BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
1752129198Scognet	{ "arm8.branchpredict",	BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
1753129198Scognet	{ NULL,			IGN, IGN, 0 }
1754129198Scognet};
1755129198Scognet
1756129198Scognetvoid
1757129198Scognetarm8_setup(args)
1758129198Scognet	char *args;
1759129198Scognet{
1760129198Scognet	int integer;
1761129198Scognet	int cpuctrl, cpuctrlmask;
1762129198Scognet	int clocktest;
1763129198Scognet	int setclock = 0;
1764129198Scognet
1765129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1766129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1767129198Scognet		 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE;
1768129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1769129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1770129198Scognet		 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE
1771129198Scognet		 | CPU_CONTROL_BPRD_ENABLE | CPU_CONTROL_ROM_ENABLE
1772129198Scognet		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE;
1773129198Scognet
1774129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1775129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1776129198Scognet#endif
1777129198Scognet
1778129198Scognet	cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl);
1779129198Scognet	cpuctrl = parse_cpu_options(args, arm8_options, cpuctrl);
1780129198Scognet
1781129198Scognet#ifdef __ARMEB__
1782129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1783129198Scognet#endif
1784129198Scognet
1785129198Scognet	/* Get clock configuration */
1786129198Scognet	clocktest = arm8_clock_config(0, 0) & 0x0f;
1787129198Scognet
1788129198Scognet	/* Special ARM8 clock and test configuration */
1789129198Scognet	if (get_bootconf_option(args, "arm8.clock.reset", BOOTOPT_TYPE_BOOLEAN, &integer)) {
1790129198Scognet		clocktest = 0;
1791129198Scognet		setclock = 1;
1792129198Scognet	}
1793129198Scognet	if (get_bootconf_option(args, "arm8.clock.dynamic", BOOTOPT_TYPE_BOOLEAN, &integer)) {
1794129198Scognet		if (integer)
1795129198Scognet			clocktest |= 0x01;
1796129198Scognet		else
1797129198Scognet			clocktest &= ~(0x01);
1798129198Scognet		setclock = 1;
1799129198Scognet	}
1800129198Scognet	if (get_bootconf_option(args, "arm8.clock.sync", BOOTOPT_TYPE_BOOLEAN, &integer)) {
1801129198Scognet		if (integer)
1802129198Scognet			clocktest |= 0x02;
1803129198Scognet		else
1804129198Scognet			clocktest &= ~(0x02);
1805129198Scognet		setclock = 1;
1806129198Scognet	}
1807129198Scognet	if (get_bootconf_option(args, "arm8.clock.fast", BOOTOPT_TYPE_BININT, &integer)) {
1808129198Scognet		clocktest = (clocktest & ~0xc0) | (integer & 3) << 2;
1809129198Scognet		setclock = 1;
1810129198Scognet	}
1811129198Scognet	if (get_bootconf_option(args, "arm8.test", BOOTOPT_TYPE_BININT, &integer)) {
1812129198Scognet		clocktest |= (integer & 7) << 5;
1813129198Scognet		setclock = 1;
1814129198Scognet	}
1815129198Scognet
1816129198Scognet	/* Clear out the cache */
1817129198Scognet	cpu_idcache_wbinv_all();
1818129198Scognet
1819129198Scognet	/* Set the control register */
1820129198Scognet	ctrl = cpuctrl;
1821129198Scognet	cpu_control(0xffffffff, cpuctrl);
1822129198Scognet
1823129198Scognet	/* Set the clock/test register */
1824129198Scognet	if (setclock)
1825129198Scognet		arm8_clock_config(0x7f, clocktest);
1826129198Scognet}
1827129198Scognet#endif	/* CPU_ARM8 */
1828129198Scognet
1829129198Scognet#ifdef CPU_ARM9
1830129198Scognetstruct cpu_option arm9_options[] = {
1831129198Scognet	{ "cpu.cache",		BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1832129198Scognet	{ "cpu.nocache",	OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1833129198Scognet	{ "arm9.cache",	BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1834129198Scognet	{ "arm9.icache",	BIC, OR,  CPU_CONTROL_IC_ENABLE },
1835129198Scognet	{ "arm9.dcache",	BIC, OR,  CPU_CONTROL_DC_ENABLE },
1836129198Scognet	{ "cpu.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1837129198Scognet	{ "cpu.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1838129198Scognet	{ "arm9.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1839129198Scognet	{ NULL,			IGN, IGN, 0 }
1840129198Scognet};
1841129198Scognet
1842129198Scognetvoid
1843129198Scognetarm9_setup(args)
1844129198Scognet	char *args;
1845129198Scognet{
1846129198Scognet	int cpuctrl, cpuctrlmask;
1847129198Scognet
1848129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1849129198Scognet	    | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1850129198Scognet	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1851146605Scognet	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE;
1852129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1853129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1854129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1855129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
1856129198Scognet		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
1857146605Scognet		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_VECRELOC
1858146605Scognet		 | CPU_CONTROL_ROUNDROBIN;
1859129198Scognet
1860129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1861129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1862129198Scognet#endif
1863129198Scognet
1864129198Scognet	cpuctrl = parse_cpu_options(args, arm9_options, cpuctrl);
1865129198Scognet
1866129198Scognet#ifdef __ARMEB__
1867129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1868129198Scognet#endif
1869142050Scognet	if (vector_page == ARM_VECTORS_HIGH)
1870142050Scognet		cpuctrl |= CPU_CONTROL_VECRELOC;
1871129198Scognet
1872129198Scognet	/* Clear out the cache */
1873129198Scognet	cpu_idcache_wbinv_all();
1874129198Scognet
1875129198Scognet	/* Set the control register */
1876146605Scognet	cpu_control(cpuctrlmask, cpuctrl);
1877129198Scognet	ctrl = cpuctrl;
1878129198Scognet
1879129198Scognet}
1880129198Scognet#endif	/* CPU_ARM9 */
1881129198Scognet
1882129198Scognet#ifdef CPU_ARM10
1883129198Scognetstruct cpu_option arm10_options[] = {
1884129198Scognet	{ "cpu.cache",		BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1885129198Scognet	{ "cpu.nocache",	OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1886129198Scognet	{ "arm10.cache",	BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1887129198Scognet	{ "arm10.icache",	BIC, OR,  CPU_CONTROL_IC_ENABLE },
1888129198Scognet	{ "arm10.dcache",	BIC, OR,  CPU_CONTROL_DC_ENABLE },
1889129198Scognet	{ "cpu.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1890129198Scognet	{ "cpu.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1891129198Scognet	{ "arm10.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1892129198Scognet	{ NULL,			IGN, IGN, 0 }
1893129198Scognet};
1894129198Scognet
1895129198Scognetvoid
1896129198Scognetarm10_setup(args)
1897129198Scognet	char *args;
1898129198Scognet{
1899129198Scognet	int cpuctrl, cpuctrlmask;
1900129198Scognet
1901129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
1902129198Scognet	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1903129198Scognet	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE;
1904129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
1905129198Scognet	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1906129198Scognet	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
1907129198Scognet	    | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
1908129198Scognet	    | CPU_CONTROL_BPRD_ENABLE
1909129198Scognet	    | CPU_CONTROL_ROUNDROBIN | CPU_CONTROL_CPCLK;
1910129198Scognet
1911129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1912129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1913129198Scognet#endif
1914129198Scognet
1915129198Scognet	cpuctrl = parse_cpu_options(args, arm10_options, cpuctrl);
1916129198Scognet
1917129198Scognet#ifdef __ARMEB__
1918129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1919129198Scognet#endif
1920129198Scognet
1921129198Scognet	/* Clear out the cache */
1922129198Scognet	cpu_idcache_wbinv_all();
1923129198Scognet
1924129198Scognet	/* Now really make sure they are clean.  */
1925129198Scognet	asm volatile ("mcr\tp15, 0, r0, c7, c7, 0" : : );
1926129198Scognet
1927129198Scognet	/* Set the control register */
1928129198Scognet	ctrl = cpuctrl;
1929129198Scognet	cpu_control(0xffffffff, cpuctrl);
1930129198Scognet
1931129198Scognet	/* And again. */
1932129198Scognet	cpu_idcache_wbinv_all();
1933129198Scognet}
1934129198Scognet#endif	/* CPU_ARM10 */
1935129198Scognet
1936129198Scognet#ifdef CPU_SA110
1937129198Scognetstruct cpu_option sa110_options[] = {
1938129198Scognet#ifdef COMPAT_12
1939129198Scognet	{ "nocache",		IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1940129198Scognet	{ "nowritebuf",		IGN, BIC, CPU_CONTROL_WBUF_ENABLE },
1941129198Scognet#endif	/* COMPAT_12 */
1942129198Scognet	{ "cpu.cache",		BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1943129198Scognet	{ "cpu.nocache",	OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1944129198Scognet	{ "sa110.cache",	BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1945129198Scognet	{ "sa110.icache",	BIC, OR,  CPU_CONTROL_IC_ENABLE },
1946129198Scognet	{ "sa110.dcache",	BIC, OR,  CPU_CONTROL_DC_ENABLE },
1947129198Scognet	{ "cpu.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1948129198Scognet	{ "cpu.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1949129198Scognet	{ "sa110.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1950129198Scognet	{ NULL,			IGN, IGN, 0 }
1951129198Scognet};
1952129198Scognet
1953129198Scognetvoid
1954129198Scognetsa110_setup(args)
1955129198Scognet	char *args;
1956129198Scognet{
1957129198Scognet	int cpuctrl, cpuctrlmask;
1958129198Scognet
1959129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1960129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1961129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1962129198Scognet		 | CPU_CONTROL_WBUF_ENABLE;
1963129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1964129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1965129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1966129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
1967129198Scognet		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
1968129198Scognet		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
1969129198Scognet		 | CPU_CONTROL_CPCLK;
1970129198Scognet
1971129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1972129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1973129198Scognet#endif
1974129198Scognet
1975129198Scognet	cpuctrl = parse_cpu_options(args, sa110_options, cpuctrl);
1976129198Scognet
1977129198Scognet#ifdef __ARMEB__
1978129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1979129198Scognet#endif
1980129198Scognet
1981129198Scognet	/* Clear out the cache */
1982129198Scognet	cpu_idcache_wbinv_all();
1983129198Scognet
1984129198Scognet	/* Set the control register */
1985129198Scognet	ctrl = cpuctrl;
1986129198Scognet/*	cpu_control(cpuctrlmask, cpuctrl);*/
1987129198Scognet	cpu_control(0xffffffff, cpuctrl);
1988129198Scognet
1989129198Scognet	/*
1990129198Scognet	 * enable clockswitching, note that this doesn't read or write to r0,
1991129198Scognet	 * r0 is just to make it valid asm
1992129198Scognet	 */
1993129198Scognet	__asm ("mcr 15, 0, r0, c15, c1, 2");
1994129198Scognet}
1995129198Scognet#endif	/* CPU_SA110 */
1996129198Scognet
1997129198Scognet#if defined(CPU_SA1100) || defined(CPU_SA1110)
1998129198Scognetstruct cpu_option sa11x0_options[] = {
1999129198Scognet#ifdef COMPAT_12
2000129198Scognet	{ "nocache",		IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2001129198Scognet	{ "nowritebuf",		IGN, BIC, CPU_CONTROL_WBUF_ENABLE },
2002129198Scognet#endif	/* COMPAT_12 */
2003129198Scognet	{ "cpu.cache",		BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2004129198Scognet	{ "cpu.nocache",	OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2005129198Scognet	{ "sa11x0.cache",	BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2006129198Scognet	{ "sa11x0.icache",	BIC, OR,  CPU_CONTROL_IC_ENABLE },
2007129198Scognet	{ "sa11x0.dcache",	BIC, OR,  CPU_CONTROL_DC_ENABLE },
2008129198Scognet	{ "cpu.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2009129198Scognet	{ "cpu.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
2010129198Scognet	{ "sa11x0.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2011129198Scognet	{ NULL,			IGN, IGN, 0 }
2012129198Scognet};
2013129198Scognet
2014129198Scognetvoid
2015129198Scognetsa11x0_setup(args)
2016129198Scognet	char *args;
2017129198Scognet{
2018129198Scognet	int cpuctrl, cpuctrlmask;
2019129198Scognet
2020129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2021129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2022129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2023129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE;
2024129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2025129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2026129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2027129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
2028129198Scognet		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
2029129198Scognet		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
2030129198Scognet		 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC;
2031129198Scognet
2032129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2033129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2034129198Scognet#endif
2035129198Scognet
2036129198Scognet
2037129198Scognet	cpuctrl = parse_cpu_options(args, sa11x0_options, cpuctrl);
2038129198Scognet
2039129198Scognet#ifdef __ARMEB__
2040129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2041129198Scognet#endif
2042129198Scognet
2043129198Scognet	if (vector_page == ARM_VECTORS_HIGH)
2044129198Scognet		cpuctrl |= CPU_CONTROL_VECRELOC;
2045129198Scognet	/* Clear out the cache */
2046129198Scognet	cpu_idcache_wbinv_all();
2047129198Scognet	/* Set the control register */
2048129198Scognet	ctrl = cpuctrl;
2049129198Scognet	cpu_control(0xffffffff, cpuctrl);
2050129198Scognet}
2051129198Scognet#endif	/* CPU_SA1100 || CPU_SA1110 */
2052129198Scognet
2053129198Scognet#if defined(CPU_IXP12X0)
2054129198Scognetstruct cpu_option ixp12x0_options[] = {
2055129198Scognet	{ "cpu.cache",		BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2056129198Scognet	{ "cpu.nocache",	OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2057129198Scognet	{ "ixp12x0.cache",	BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2058129198Scognet	{ "ixp12x0.icache",	BIC, OR,  CPU_CONTROL_IC_ENABLE },
2059129198Scognet	{ "ixp12x0.dcache",	BIC, OR,  CPU_CONTROL_DC_ENABLE },
2060129198Scognet	{ "cpu.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2061129198Scognet	{ "cpu.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
2062129198Scognet	{ "ixp12x0.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2063129198Scognet	{ NULL,			IGN, IGN, 0 }
2064129198Scognet};
2065129198Scognet
2066129198Scognetvoid
2067129198Scognetixp12x0_setup(args)
2068129198Scognet	char *args;
2069129198Scognet{
2070129198Scognet	int cpuctrl, cpuctrlmask;
2071129198Scognet
2072129198Scognet
2073129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE
2074129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_SYST_ENABLE
2075129198Scognet		 | CPU_CONTROL_IC_ENABLE;
2076129198Scognet
2077129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_AFLT_ENABLE
2078129198Scognet		 | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE
2079129198Scognet		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_SYST_ENABLE
2080129198Scognet		 | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_IC_ENABLE
2081129198Scognet		 | CPU_CONTROL_VECRELOC;
2082129198Scognet
2083129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2084129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2085129198Scognet#endif
2086129198Scognet
2087129198Scognet	cpuctrl = parse_cpu_options(args, ixp12x0_options, cpuctrl);
2088129198Scognet
2089129198Scognet#ifdef __ARMEB__
2090129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2091129198Scognet#endif
2092129198Scognet
2093129198Scognet	if (vector_page == ARM_VECTORS_HIGH)
2094129198Scognet		cpuctrl |= CPU_CONTROL_VECRELOC;
2095129198Scognet
2096129198Scognet	/* Clear out the cache */
2097129198Scognet	cpu_idcache_wbinv_all();
2098129198Scognet
2099129198Scognet	/* Set the control register */
2100129198Scognet	ctrl = cpuctrl;
2101129198Scognet	/* cpu_control(0xffffffff, cpuctrl); */
2102129198Scognet	cpu_control(cpuctrlmask, cpuctrl);
2103129198Scognet}
2104129198Scognet#endif /* CPU_IXP12X0 */
2105129198Scognet
2106129198Scognet#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
2107129198Scognet    defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425)
2108129198Scognetstruct cpu_option xscale_options[] = {
2109129198Scognet#ifdef COMPAT_12
2110129198Scognet	{ "branchpredict", 	BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
2111129198Scognet	{ "nocache",		IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2112129198Scognet#endif	/* COMPAT_12 */
2113129198Scognet	{ "cpu.branchpredict", 	BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
2114129198Scognet	{ "cpu.cache",		BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2115129198Scognet	{ "cpu.nocache",	OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2116129198Scognet	{ "xscale.branchpredict", BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
2117129198Scognet	{ "xscale.cache",	BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2118129198Scognet	{ "xscale.icache",	BIC, OR,  CPU_CONTROL_IC_ENABLE },
2119129198Scognet	{ "xscale.dcache",	BIC, OR,  CPU_CONTROL_DC_ENABLE },
2120129198Scognet	{ NULL,			IGN, IGN, 0 }
2121129198Scognet};
2122129198Scognet
2123129198Scognetvoid
2124129198Scognetxscale_setup(args)
2125129198Scognet	char *args;
2126129198Scognet{
2127129198Scognet	uint32_t auxctl;
2128129198Scognet	int cpuctrl, cpuctrlmask;
2129129198Scognet
2130129198Scognet	/*
2131129198Scognet	 * The XScale Write Buffer is always enabled.  Our option
2132129198Scognet	 * is to enable/disable coalescing.  Note that bits 6:3
2133129198Scognet	 * must always be enabled.
2134129198Scognet	 */
2135129198Scognet
2136129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2137129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2138129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2139129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
2140129198Scognet		 | CPU_CONTROL_BPRD_ENABLE;
2141129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2142129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2143129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2144129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
2145129198Scognet		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
2146129198Scognet		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
2147129198Scognet		 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC;
2148129198Scognet
2149129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2150129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2151129198Scognet#endif
2152129198Scognet
2153129198Scognet	cpuctrl = parse_cpu_options(args, xscale_options, cpuctrl);
2154129198Scognet
2155129198Scognet#ifdef __ARMEB__
2156129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2157129198Scognet#endif
2158129198Scognet
2159129198Scognet	if (vector_page == ARM_VECTORS_HIGH)
2160129198Scognet		cpuctrl |= CPU_CONTROL_VECRELOC;
2161129198Scognet
2162129198Scognet	/* Clear out the cache */
2163129198Scognet	cpu_idcache_wbinv_all();
2164129198Scognet
2165129198Scognet	/*
2166129198Scognet	 * Set the control register.  Note that bits 6:3 must always
2167129198Scognet	 * be set to 1.
2168129198Scognet	 */
2169129198Scognet	ctrl = cpuctrl;
2170129198Scognet/*	cpu_control(cpuctrlmask, cpuctrl);*/
2171129198Scognet	cpu_control(0xffffffff, cpuctrl);
2172129198Scognet
2173129198Scognet	/* Make sure write coalescing is turned on */
2174129198Scognet	__asm __volatile("mrc p15, 0, %0, c1, c0, 1"
2175129198Scognet		: "=r" (auxctl));
2176129198Scognet#ifdef XSCALE_NO_COALESCE_WRITES
2177129198Scognet	auxctl |= XSCALE_AUXCTL_K;
2178129198Scognet#else
2179129198Scognet	auxctl &= ~XSCALE_AUXCTL_K;
2180129198Scognet#endif
2181129198Scognet	__asm __volatile("mcr p15, 0, %0, c1, c0, 1"
2182129198Scognet		: : "r" (auxctl));
2183129198Scognet}
2184129198Scognet#endif	/* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */
2185