cpufunc.c revision 257217
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 257217 2013-10-27 17:09:23Z ian $");
49129198Scognet
50129198Scognet#include <sys/param.h>
51129198Scognet#include <sys/systm.h>
52129198Scognet#include <sys/lock.h>
53129198Scognet#include <sys/mutex.h>
54132472Scognet#include <sys/bus.h>
55132472Scognet#include <machine/bus.h>
56129198Scognet#include <machine/cpu.h>
57129198Scognet#include <machine/disassem.h>
58129198Scognet
59129198Scognet#include <vm/vm.h>
60129198Scognet#include <vm/pmap.h>
61166655Scognet#include <vm/uma.h>
62129198Scognet
63129198Scognet#include <machine/cpuconf.h>
64129198Scognet#include <machine/cpufunc.h>
65129198Scognet#include <machine/bootconfig.h>
66129198Scognet
67129198Scognet#ifdef CPU_XSCALE_80200
68135646Scognet#include <arm/xscale/i80200/i80200reg.h>
69135646Scognet#include <arm/xscale/i80200/i80200var.h>
70129198Scognet#endif
71129198Scognet
72161592Scognet#if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219)
73135646Scognet#include <arm/xscale/i80321/i80321reg.h>
74135646Scognet#include <arm/xscale/i80321/i80321var.h>
75129198Scognet#endif
76129198Scognet
77243579Smarcel/*
78243579Smarcel * Some definitions in i81342reg.h clash with i80321reg.h.
79243579Smarcel * This only happens for the LINT kernel. As it happens,
80243579Smarcel * we don't need anything from i81342reg.h that we already
81243579Smarcel * got from somewhere else during a LINT compile.
82243579Smarcel */
83243579Smarcel#if defined(CPU_XSCALE_81342) && !defined(COMPILING_LINT)
84164080Scognet#include <arm/xscale/i8134x/i81342reg.h>
85164080Scognet#endif
86164080Scognet
87129198Scognet#ifdef CPU_XSCALE_IXP425
88135646Scognet#include <arm/xscale/ixp425/ixp425reg.h>
89135646Scognet#include <arm/xscale/ixp425/ixp425var.h>
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
107239268Sgonzou_int	arm_cache_level;
108239268Sgonzou_int	arm_cache_type[14];
109239268Sgonzou_int	arm_cache_loc;
110239268Sgonzo
111129198Scognet/* 1 == use cpu_sleep(), 0 == don't */
112129198Scognetint cpu_do_powersave;
113129198Scognetint ctrl;
114129198Scognet
115129198Scognet#ifdef CPU_ARM7TDMI
116129198Scognetstruct cpu_functions arm7tdmi_cpufuncs = {
117129198Scognet	/* CPU functions */
118129198Scognet
119129198Scognet	cpufunc_id,			/* id			*/
120129198Scognet	cpufunc_nullop,			/* cpwait		*/
121129198Scognet
122129198Scognet	/* MMU functions */
123129198Scognet
124129198Scognet	cpufunc_control,		/* control		*/
125129198Scognet	cpufunc_domains,		/* domain		*/
126129198Scognet	arm7tdmi_setttb,		/* setttb		*/
127129198Scognet	cpufunc_faultstatus,		/* faultstatus		*/
128129198Scognet	cpufunc_faultaddress,		/* faultaddress		*/
129129198Scognet
130129198Scognet	/* TLB functions */
131129198Scognet
132129198Scognet	arm7tdmi_tlb_flushID,		/* tlb_flushID		*/
133129198Scognet	arm7tdmi_tlb_flushID_SE,	/* tlb_flushID_SE	*/
134129198Scognet	arm7tdmi_tlb_flushID,		/* tlb_flushI		*/
135129198Scognet	arm7tdmi_tlb_flushID_SE,	/* tlb_flushI_SE	*/
136129198Scognet	arm7tdmi_tlb_flushID,		/* tlb_flushD		*/
137129198Scognet	arm7tdmi_tlb_flushID_SE,	/* tlb_flushD_SE	*/
138129198Scognet
139129198Scognet	/* Cache operations */
140129198Scognet
141129198Scognet	cpufunc_nullop,			/* icache_sync_all	*/
142129198Scognet	(void *)cpufunc_nullop,		/* icache_sync_range	*/
143129198Scognet
144129198Scognet	arm7tdmi_cache_flushID,		/* dcache_wbinv_all	*/
145129198Scognet	(void *)arm7tdmi_cache_flushID,	/* dcache_wbinv_range	*/
146129198Scognet	(void *)arm7tdmi_cache_flushID,	/* dcache_inv_range	*/
147129198Scognet	(void *)cpufunc_nullop,		/* dcache_wb_range	*/
148129198Scognet
149129198Scognet	arm7tdmi_cache_flushID,		/* idcache_wbinv_all	*/
150129198Scognet	(void *)arm7tdmi_cache_flushID,	/* idcache_wbinv_range	*/
151171618Scognet	cpufunc_nullop,			/* l2cache_wbinv_all	*/
152171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
153171781Scognet	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
154171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
155129198Scognet
156129198Scognet	/* Other functions */
157129198Scognet
158129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
159129198Scognet	cpufunc_nullop,			/* drain_writebuf	*/
160129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
161129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
162129198Scognet
163129198Scognet	(void *)cpufunc_nullop,		/* sleep		*/
164129198Scognet
165129198Scognet	/* Soft functions */
166129198Scognet
167129198Scognet	late_abort_fixup,		/* dataabt_fixup	*/
168129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
169129198Scognet
170129198Scognet	arm7tdmi_context_switch,	/* context_switch	*/
171129198Scognet
172129198Scognet	arm7tdmi_setup			/* cpu setup		*/
173129198Scognet
174129198Scognet};
175129198Scognet#endif	/* CPU_ARM7TDMI */
176129198Scognet
177129198Scognet#ifdef CPU_ARM8
178129198Scognetstruct cpu_functions arm8_cpufuncs = {
179129198Scognet	/* CPU functions */
180129198Scognet
181129198Scognet	cpufunc_id,			/* id			*/
182129198Scognet	cpufunc_nullop,			/* cpwait		*/
183129198Scognet
184129198Scognet	/* MMU functions */
185129198Scognet
186129198Scognet	cpufunc_control,		/* control		*/
187129198Scognet	cpufunc_domains,		/* domain		*/
188129198Scognet	arm8_setttb,			/* setttb		*/
189129198Scognet	cpufunc_faultstatus,		/* faultstatus		*/
190129198Scognet	cpufunc_faultaddress,		/* faultaddress		*/
191129198Scognet
192129198Scognet	/* TLB functions */
193129198Scognet
194129198Scognet	arm8_tlb_flushID,		/* tlb_flushID		*/
195129198Scognet	arm8_tlb_flushID_SE,		/* tlb_flushID_SE	*/
196129198Scognet	arm8_tlb_flushID,		/* tlb_flushI		*/
197129198Scognet	arm8_tlb_flushID_SE,		/* tlb_flushI_SE	*/
198129198Scognet	arm8_tlb_flushID,		/* tlb_flushD		*/
199129198Scognet	arm8_tlb_flushID_SE,		/* tlb_flushD_SE	*/
200129198Scognet
201129198Scognet	/* Cache operations */
202129198Scognet
203129198Scognet	cpufunc_nullop,			/* icache_sync_all	*/
204129198Scognet	(void *)cpufunc_nullop,		/* icache_sync_range	*/
205129198Scognet
206129198Scognet	arm8_cache_purgeID,		/* dcache_wbinv_all	*/
207129198Scognet	(void *)arm8_cache_purgeID,	/* dcache_wbinv_range	*/
208129198Scognet/*XXX*/	(void *)arm8_cache_purgeID,	/* dcache_inv_range	*/
209129198Scognet	(void *)arm8_cache_cleanID,	/* dcache_wb_range	*/
210129198Scognet
211129198Scognet	arm8_cache_purgeID,		/* idcache_wbinv_all	*/
212129198Scognet	(void *)arm8_cache_purgeID,	/* idcache_wbinv_range	*/
213171618Scognet	cpufunc_nullop,			/* l2cache_wbinv_all	*/
214171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
215171781Scognet	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
216171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
217129198Scognet
218129198Scognet	/* Other functions */
219129198Scognet
220129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
221129198Scognet	cpufunc_nullop,			/* drain_writebuf	*/
222129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
223129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
224129198Scognet
225129198Scognet	(void *)cpufunc_nullop,		/* sleep		*/
226129198Scognet
227129198Scognet	/* Soft functions */
228129198Scognet
229129198Scognet	cpufunc_null_fixup,		/* dataabt_fixup	*/
230129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
231129198Scognet
232129198Scognet	arm8_context_switch,		/* context_switch	*/
233129198Scognet
234129198Scognet	arm8_setup			/* cpu setup		*/
235236991Simp};
236129198Scognet#endif	/* CPU_ARM8 */
237129198Scognet
238129198Scognet#ifdef CPU_ARM9
239129198Scognetstruct cpu_functions arm9_cpufuncs = {
240129198Scognet	/* CPU functions */
241129198Scognet
242129198Scognet	cpufunc_id,			/* id			*/
243129198Scognet	cpufunc_nullop,			/* cpwait		*/
244129198Scognet
245129198Scognet	/* MMU functions */
246129198Scognet
247129198Scognet	cpufunc_control,		/* control		*/
248129198Scognet	cpufunc_domains,		/* Domain		*/
249129198Scognet	arm9_setttb,			/* Setttb		*/
250129198Scognet	cpufunc_faultstatus,		/* Faultstatus		*/
251129198Scognet	cpufunc_faultaddress,		/* Faultaddress		*/
252129198Scognet
253129198Scognet	/* TLB functions */
254129198Scognet
255129198Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
256129198Scognet	arm9_tlb_flushID_SE,		/* tlb_flushID_SE	*/
257129198Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
258129198Scognet	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
259129198Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
260129198Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
261129198Scognet
262129198Scognet	/* Cache operations */
263129198Scognet
264146605Scognet	arm9_icache_sync_all,		/* icache_sync_all	*/
265146605Scognet	arm9_icache_sync_range,		/* icache_sync_range	*/
266129198Scognet
267146605Scognet	arm9_dcache_wbinv_all,		/* dcache_wbinv_all	*/
268146605Scognet	arm9_dcache_wbinv_range,	/* dcache_wbinv_range	*/
269195798Sraj	arm9_dcache_inv_range,		/* dcache_inv_range	*/
270146605Scognet	arm9_dcache_wb_range,		/* dcache_wb_range	*/
271129198Scognet
272146605Scognet	arm9_idcache_wbinv_all,		/* idcache_wbinv_all	*/
273146605Scognet	arm9_idcache_wbinv_range,	/* idcache_wbinv_range	*/
274171618Scognet	cpufunc_nullop,			/* l2cache_wbinv_all	*/
275171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
276171781Scognet	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
277171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
278129198Scognet
279129198Scognet	/* Other functions */
280129198Scognet
281129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
282129198Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
283129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
284129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
285129198Scognet
286129198Scognet	(void *)cpufunc_nullop,		/* sleep		*/
287129198Scognet
288129198Scognet	/* Soft functions */
289129198Scognet
290129198Scognet	cpufunc_null_fixup,		/* dataabt_fixup	*/
291129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
292129198Scognet
293129198Scognet	arm9_context_switch,		/* context_switch	*/
294129198Scognet
295129198Scognet	arm9_setup			/* cpu setup		*/
296129198Scognet
297129198Scognet};
298129198Scognet#endif /* CPU_ARM9 */
299129198Scognet
300172738Simp#if defined(CPU_ARM9E) || defined(CPU_ARM10)
301172738Simpstruct cpu_functions armv5_ec_cpufuncs = {
302172738Simp	/* CPU functions */
303172738Simp
304172738Simp	cpufunc_id,			/* id			*/
305172738Simp	cpufunc_nullop,			/* cpwait		*/
306172738Simp
307172738Simp	/* MMU functions */
308172738Simp
309172738Simp	cpufunc_control,		/* control		*/
310172738Simp	cpufunc_domains,		/* Domain		*/
311172738Simp	armv5_ec_setttb,		/* Setttb		*/
312172738Simp	cpufunc_faultstatus,		/* Faultstatus		*/
313172738Simp	cpufunc_faultaddress,		/* Faultaddress		*/
314172738Simp
315172738Simp	/* TLB functions */
316172738Simp
317172738Simp	armv4_tlb_flushID,		/* tlb_flushID		*/
318172738Simp	arm10_tlb_flushID_SE,		/* tlb_flushID_SE	*/
319172738Simp	armv4_tlb_flushI,		/* tlb_flushI		*/
320172738Simp	arm10_tlb_flushI_SE,		/* tlb_flushI_SE	*/
321172738Simp	armv4_tlb_flushD,		/* tlb_flushD		*/
322172738Simp	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
323172738Simp
324172738Simp	/* Cache operations */
325172738Simp
326172738Simp	armv5_ec_icache_sync_all,	/* icache_sync_all	*/
327172738Simp	armv5_ec_icache_sync_range,	/* icache_sync_range	*/
328172738Simp
329172738Simp	armv5_ec_dcache_wbinv_all,	/* dcache_wbinv_all	*/
330172738Simp	armv5_ec_dcache_wbinv_range,	/* dcache_wbinv_range	*/
331195798Sraj	armv5_ec_dcache_inv_range,	/* dcache_inv_range	*/
332172738Simp	armv5_ec_dcache_wb_range,	/* dcache_wb_range	*/
333172738Simp
334172738Simp	armv5_ec_idcache_wbinv_all,	/* idcache_wbinv_all	*/
335172738Simp	armv5_ec_idcache_wbinv_range,	/* idcache_wbinv_range	*/
336172738Simp
337173442Scognet	cpufunc_nullop,                 /* l2cache_wbinv_all    */
338173442Scognet	(void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
339173442Scognet      	(void *)cpufunc_nullop,         /* l2cache_inv_range    */
340173442Scognet	(void *)cpufunc_nullop,         /* l2cache_wb_range     */
341236991Simp
342172738Simp	/* Other functions */
343172738Simp
344172738Simp	cpufunc_nullop,			/* flush_prefetchbuf	*/
345172738Simp	armv4_drain_writebuf,		/* drain_writebuf	*/
346172738Simp	cpufunc_nullop,			/* flush_brnchtgt_C	*/
347172738Simp	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
348172738Simp
349172738Simp	(void *)cpufunc_nullop,		/* sleep		*/
350172738Simp
351172738Simp	/* Soft functions */
352172738Simp
353172738Simp	cpufunc_null_fixup,		/* dataabt_fixup	*/
354172738Simp	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
355172738Simp
356172738Simp	arm10_context_switch,		/* context_switch	*/
357172738Simp
358172738Simp	arm10_setup			/* cpu setup		*/
359172738Simp
360172738Simp};
361183835Sraj
362186933Srajstruct cpu_functions sheeva_cpufuncs = {
363183835Sraj	/* CPU functions */
364183835Sraj
365183835Sraj	cpufunc_id,			/* id			*/
366183835Sraj	cpufunc_nullop,			/* cpwait		*/
367183835Sraj
368183835Sraj	/* MMU functions */
369183835Sraj
370183835Sraj	cpufunc_control,		/* control		*/
371183835Sraj	cpufunc_domains,		/* Domain		*/
372186933Sraj	sheeva_setttb,			/* Setttb		*/
373183835Sraj	cpufunc_faultstatus,		/* Faultstatus		*/
374183835Sraj	cpufunc_faultaddress,		/* Faultaddress		*/
375183835Sraj
376183835Sraj	/* TLB functions */
377183835Sraj
378183835Sraj	armv4_tlb_flushID,		/* tlb_flushID		*/
379183835Sraj	arm10_tlb_flushID_SE,		/* tlb_flushID_SE	*/
380183835Sraj	armv4_tlb_flushI,		/* tlb_flushI		*/
381183835Sraj	arm10_tlb_flushI_SE,		/* tlb_flushI_SE	*/
382183835Sraj	armv4_tlb_flushD,		/* tlb_flushD		*/
383183835Sraj	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
384183835Sraj
385183835Sraj	/* Cache operations */
386183835Sraj
387183835Sraj	armv5_ec_icache_sync_all,	/* icache_sync_all	*/
388183835Sraj	armv5_ec_icache_sync_range,	/* icache_sync_range	*/
389183835Sraj
390183835Sraj	armv5_ec_dcache_wbinv_all,	/* dcache_wbinv_all	*/
391186933Sraj	sheeva_dcache_wbinv_range,	/* dcache_wbinv_range	*/
392186933Sraj	sheeva_dcache_inv_range,	/* dcache_inv_range	*/
393186933Sraj	sheeva_dcache_wb_range,		/* dcache_wb_range	*/
394183835Sraj
395183835Sraj	armv5_ec_idcache_wbinv_all,	/* idcache_wbinv_all	*/
396186933Sraj	sheeva_idcache_wbinv_range,	/* idcache_wbinv_all	*/
397183835Sraj
398186933Sraj	sheeva_l2cache_wbinv_all,	/* l2cache_wbinv_all    */
399186933Sraj	sheeva_l2cache_wbinv_range,	/* l2cache_wbinv_range  */
400186933Sraj	sheeva_l2cache_inv_range,	/* l2cache_inv_range    */
401186933Sraj	sheeva_l2cache_wb_range,	/* l2cache_wb_range     */
402183835Sraj
403183835Sraj	/* Other functions */
404183835Sraj
405183835Sraj	cpufunc_nullop,			/* flush_prefetchbuf	*/
406183835Sraj	armv4_drain_writebuf,		/* drain_writebuf	*/
407183835Sraj	cpufunc_nullop,			/* flush_brnchtgt_C	*/
408183835Sraj	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
409183835Sraj
410212825Smav	sheeva_cpu_sleep,		/* sleep		*/
411183835Sraj
412183835Sraj	/* Soft functions */
413183835Sraj
414183835Sraj	cpufunc_null_fixup,		/* dataabt_fixup	*/
415183835Sraj	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
416183835Sraj
417183835Sraj	arm10_context_switch,		/* context_switch	*/
418183835Sraj
419183835Sraj	arm10_setup			/* cpu setup		*/
420183835Sraj};
421172738Simp#endif /* CPU_ARM9E || CPU_ARM10 */
422172738Simp
423129198Scognet#ifdef CPU_ARM10
424129198Scognetstruct cpu_functions arm10_cpufuncs = {
425129198Scognet	/* CPU functions */
426129198Scognet
427129198Scognet	cpufunc_id,			/* id			*/
428129198Scognet	cpufunc_nullop,			/* cpwait		*/
429129198Scognet
430129198Scognet	/* MMU functions */
431129198Scognet
432129198Scognet	cpufunc_control,		/* control		*/
433129198Scognet	cpufunc_domains,		/* Domain		*/
434129198Scognet	arm10_setttb,			/* Setttb		*/
435129198Scognet	cpufunc_faultstatus,		/* Faultstatus		*/
436129198Scognet	cpufunc_faultaddress,		/* Faultaddress		*/
437129198Scognet
438129198Scognet	/* TLB functions */
439129198Scognet
440129198Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
441129198Scognet	arm10_tlb_flushID_SE,		/* tlb_flushID_SE	*/
442129198Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
443129198Scognet	arm10_tlb_flushI_SE,		/* tlb_flushI_SE	*/
444129198Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
445129198Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
446129198Scognet
447129198Scognet	/* Cache operations */
448129198Scognet
449129198Scognet	arm10_icache_sync_all,		/* icache_sync_all	*/
450129198Scognet	arm10_icache_sync_range,	/* icache_sync_range	*/
451129198Scognet
452129198Scognet	arm10_dcache_wbinv_all,		/* dcache_wbinv_all	*/
453129198Scognet	arm10_dcache_wbinv_range,	/* dcache_wbinv_range	*/
454129198Scognet	arm10_dcache_inv_range,		/* dcache_inv_range	*/
455129198Scognet	arm10_dcache_wb_range,		/* dcache_wb_range	*/
456129198Scognet
457129198Scognet	arm10_idcache_wbinv_all,	/* idcache_wbinv_all	*/
458129198Scognet	arm10_idcache_wbinv_range,	/* idcache_wbinv_range	*/
459171618Scognet	cpufunc_nullop,			/* l2cache_wbinv_all	*/
460171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
461171781Scognet	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
462171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
463129198Scognet
464129198Scognet	/* Other functions */
465129198Scognet
466129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
467129198Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
468129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
469129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
470129198Scognet
471129198Scognet	(void *)cpufunc_nullop,		/* sleep		*/
472129198Scognet
473129198Scognet	/* Soft functions */
474129198Scognet
475129198Scognet	cpufunc_null_fixup,		/* dataabt_fixup	*/
476129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
477129198Scognet
478129198Scognet	arm10_context_switch,		/* context_switch	*/
479129198Scognet
480129198Scognet	arm10_setup			/* cpu setup		*/
481129198Scognet
482129198Scognet};
483129198Scognet#endif /* CPU_ARM10 */
484129198Scognet
485239268Sgonzo#ifdef CPU_MV_PJ4B
486239268Sgonzostruct cpu_functions pj4bv7_cpufuncs = {
487239268Sgonzo	/* CPU functions */
488239268Sgonzo
489239268Sgonzo	cpufunc_id,			/* id			*/
490239268Sgonzo	arm11_drain_writebuf,		/* cpwait		*/
491239268Sgonzo
492239268Sgonzo	/* MMU functions */
493239268Sgonzo
494239268Sgonzo	cpufunc_control,		/* control		*/
495239268Sgonzo	cpufunc_domains,		/* Domain		*/
496239268Sgonzo	pj4b_setttb,			/* Setttb		*/
497239268Sgonzo	cpufunc_faultstatus,		/* Faultstatus		*/
498239268Sgonzo	cpufunc_faultaddress,		/* Faultaddress		*/
499239268Sgonzo
500239268Sgonzo	/* TLB functions */
501239268Sgonzo
502239268Sgonzo	armv7_tlb_flushID,		/* tlb_flushID		*/
503239268Sgonzo	armv7_tlb_flushID_SE,		/* tlb_flushID_SE	*/
504239268Sgonzo	armv7_tlb_flushID,		/* tlb_flushI		*/
505239268Sgonzo	armv7_tlb_flushID_SE,		/* tlb_flushI_SE	*/
506239268Sgonzo	armv7_tlb_flushID,		/* tlb_flushD		*/
507239268Sgonzo	armv7_tlb_flushID_SE,		/* tlb_flushD_SE	*/
508239268Sgonzo
509239268Sgonzo	/* Cache operations */
510239268Sgonzo	armv7_idcache_wbinv_all,	/* icache_sync_all	*/
511239268Sgonzo	armv7_icache_sync_range,	/* icache_sync_range	*/
512239268Sgonzo
513239268Sgonzo	armv7_dcache_wbinv_all,		/* dcache_wbinv_all	*/
514239268Sgonzo	armv7_dcache_wbinv_range,	/* dcache_wbinv_range	*/
515239268Sgonzo	armv7_dcache_inv_range,		/* dcache_inv_range	*/
516239268Sgonzo	armv7_dcache_wb_range,		/* dcache_wb_range	*/
517239268Sgonzo
518239268Sgonzo	armv7_idcache_wbinv_all,	/* idcache_wbinv_all	*/
519239268Sgonzo	armv7_idcache_wbinv_range,	/* idcache_wbinv_all	*/
520239268Sgonzo
521239268Sgonzo	(void *)cpufunc_nullop,		/* l2cache_wbinv_all	*/
522239268Sgonzo	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
523239268Sgonzo	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
524239268Sgonzo	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
525239268Sgonzo
526239268Sgonzo	/* Other functions */
527239268Sgonzo
528239268Sgonzo	pj4b_drain_readbuf,		/* flush_prefetchbuf	*/
529239268Sgonzo	arm11_drain_writebuf,		/* drain_writebuf	*/
530239268Sgonzo	pj4b_flush_brnchtgt_all,	/* flush_brnchtgt_C	*/
531239268Sgonzo	pj4b_flush_brnchtgt_va,		/* flush_brnchtgt_E	*/
532239268Sgonzo
533239268Sgonzo	(void *)cpufunc_nullop,		/* sleep		*/
534239268Sgonzo
535239268Sgonzo	/* Soft functions */
536239268Sgonzo
537239268Sgonzo	cpufunc_null_fixup,		/* dataabt_fixup	*/
538239268Sgonzo	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
539239268Sgonzo
540239268Sgonzo	arm11_context_switch,		/* context_switch	*/
541239268Sgonzo
542239268Sgonzo	pj4bv7_setup			/* cpu setup		*/
543239268Sgonzo};
544239268Sgonzo
545239268Sgonzostruct cpu_functions pj4bv6_cpufuncs = {
546239268Sgonzo	/* CPU functions */
547239268Sgonzo
548239268Sgonzo	cpufunc_id,			/* id			*/
549239268Sgonzo	arm11_drain_writebuf,		/* cpwait		*/
550239268Sgonzo
551239268Sgonzo	/* MMU functions */
552239268Sgonzo
553239268Sgonzo	cpufunc_control,		/* control		*/
554239268Sgonzo	cpufunc_domains,		/* Domain		*/
555239268Sgonzo	pj4b_setttb,			/* Setttb		*/
556239268Sgonzo	cpufunc_faultstatus,		/* Faultstatus		*/
557239268Sgonzo	cpufunc_faultaddress,		/* Faultaddress		*/
558239268Sgonzo
559239268Sgonzo	/* TLB functions */
560239268Sgonzo
561239268Sgonzo	arm11_tlb_flushID,		/* tlb_flushID		*/
562239268Sgonzo	arm11_tlb_flushID_SE,		/* tlb_flushID_SE	*/
563239268Sgonzo	arm11_tlb_flushI,		/* tlb_flushI		*/
564239268Sgonzo	arm11_tlb_flushI_SE,		/* tlb_flushI_SE	*/
565239268Sgonzo	arm11_tlb_flushD,		/* tlb_flushD		*/
566239268Sgonzo	arm11_tlb_flushD_SE,		/* tlb_flushD_SE	*/
567239268Sgonzo
568239268Sgonzo	/* Cache operations */
569239268Sgonzo	armv6_icache_sync_all,		/* icache_sync_all	*/
570239268Sgonzo	pj4b_icache_sync_range,		/* icache_sync_range	*/
571239268Sgonzo
572239268Sgonzo	armv6_dcache_wbinv_all,		/* dcache_wbinv_all	*/
573239268Sgonzo	pj4b_dcache_wbinv_range,	/* dcache_wbinv_range	*/
574239268Sgonzo	pj4b_dcache_inv_range,		/* dcache_inv_range	*/
575239268Sgonzo	pj4b_dcache_wb_range,		/* dcache_wb_range	*/
576239268Sgonzo
577239268Sgonzo	armv6_idcache_wbinv_all,	/* idcache_wbinv_all	*/
578239268Sgonzo	pj4b_idcache_wbinv_range,	/* idcache_wbinv_all	*/
579239268Sgonzo
580239268Sgonzo	(void *)cpufunc_nullop,		/* l2cache_wbinv_all	*/
581239268Sgonzo	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
582239268Sgonzo	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
583239268Sgonzo	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
584239268Sgonzo
585239268Sgonzo	/* Other functions */
586239268Sgonzo
587239268Sgonzo	pj4b_drain_readbuf,		/* flush_prefetchbuf	*/
588239268Sgonzo	arm11_drain_writebuf,		/* drain_writebuf	*/
589239268Sgonzo	pj4b_flush_brnchtgt_all,	/* flush_brnchtgt_C	*/
590239268Sgonzo	pj4b_flush_brnchtgt_va,		/* flush_brnchtgt_E	*/
591239268Sgonzo
592239268Sgonzo	(void *)cpufunc_nullop,		/* sleep		*/
593239268Sgonzo
594239268Sgonzo	/* Soft functions */
595239268Sgonzo
596239268Sgonzo	cpufunc_null_fixup,		/* dataabt_fixup	*/
597239268Sgonzo	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
598239268Sgonzo
599239268Sgonzo	arm11_context_switch,		/* context_switch	*/
600239268Sgonzo
601239268Sgonzo	pj4bv6_setup			/* cpu setup		*/
602239268Sgonzo};
603239268Sgonzo#endif /* CPU_MV_PJ4B */
604239268Sgonzo
605129198Scognet#ifdef CPU_SA110
606129198Scognetstruct cpu_functions sa110_cpufuncs = {
607129198Scognet	/* CPU functions */
608129198Scognet
609129198Scognet	cpufunc_id,			/* id			*/
610129198Scognet	cpufunc_nullop,			/* cpwait		*/
611129198Scognet
612129198Scognet	/* MMU functions */
613129198Scognet
614129198Scognet	cpufunc_control,		/* control		*/
615129198Scognet	cpufunc_domains,		/* domain		*/
616129198Scognet	sa1_setttb,			/* setttb		*/
617129198Scognet	cpufunc_faultstatus,		/* faultstatus		*/
618129198Scognet	cpufunc_faultaddress,		/* faultaddress		*/
619129198Scognet
620129198Scognet	/* TLB functions */
621129198Scognet
622129198Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
623129198Scognet	sa1_tlb_flushID_SE,		/* tlb_flushID_SE	*/
624129198Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
625129198Scognet	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
626129198Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
627129198Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
628129198Scognet
629129198Scognet	/* Cache operations */
630129198Scognet
631129198Scognet	sa1_cache_syncI,		/* icache_sync_all	*/
632129198Scognet	sa1_cache_syncI_rng,		/* icache_sync_range	*/
633129198Scognet
634129198Scognet	sa1_cache_purgeD,		/* dcache_wbinv_all	*/
635129198Scognet	sa1_cache_purgeD_rng,		/* dcache_wbinv_range	*/
636129198Scognet/*XXX*/	sa1_cache_purgeD_rng,		/* dcache_inv_range	*/
637129198Scognet	sa1_cache_cleanD_rng,		/* dcache_wb_range	*/
638129198Scognet
639129198Scognet	sa1_cache_purgeID,		/* idcache_wbinv_all	*/
640129198Scognet	sa1_cache_purgeID_rng,		/* idcache_wbinv_range	*/
641171618Scognet	cpufunc_nullop,			/* l2cache_wbinv_all	*/
642171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
643171781Scognet	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
644171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
645129198Scognet
646129198Scognet	/* Other functions */
647129198Scognet
648129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
649129198Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
650129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
651129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
652129198Scognet
653129198Scognet	(void *)cpufunc_nullop,		/* sleep		*/
654129198Scognet
655129198Scognet	/* Soft functions */
656129198Scognet
657129198Scognet	cpufunc_null_fixup,		/* dataabt_fixup	*/
658129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
659129198Scognet
660129198Scognet	sa110_context_switch,		/* context_switch	*/
661129198Scognet
662129198Scognet	sa110_setup			/* cpu setup		*/
663236991Simp};
664129198Scognet#endif	/* CPU_SA110 */
665129198Scognet
666129198Scognet#if defined(CPU_SA1100) || defined(CPU_SA1110)
667129198Scognetstruct cpu_functions sa11x0_cpufuncs = {
668129198Scognet	/* CPU functions */
669129198Scognet
670129198Scognet	cpufunc_id,			/* id			*/
671129198Scognet	cpufunc_nullop,			/* cpwait		*/
672129198Scognet
673129198Scognet	/* MMU functions */
674129198Scognet
675129198Scognet	cpufunc_control,		/* control		*/
676129198Scognet	cpufunc_domains,		/* domain		*/
677129198Scognet	sa1_setttb,			/* setttb		*/
678129198Scognet	cpufunc_faultstatus,		/* faultstatus		*/
679129198Scognet	cpufunc_faultaddress,		/* faultaddress		*/
680129198Scognet
681129198Scognet	/* TLB functions */
682129198Scognet
683129198Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
684129198Scognet	sa1_tlb_flushID_SE,		/* tlb_flushID_SE	*/
685129198Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
686129198Scognet	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
687129198Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
688129198Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
689129198Scognet
690129198Scognet	/* Cache operations */
691129198Scognet
692129198Scognet	sa1_cache_syncI,		/* icache_sync_all	*/
693129198Scognet	sa1_cache_syncI_rng,		/* icache_sync_range	*/
694129198Scognet
695129198Scognet	sa1_cache_purgeD,		/* dcache_wbinv_all	*/
696129198Scognet	sa1_cache_purgeD_rng,		/* dcache_wbinv_range	*/
697129198Scognet/*XXX*/	sa1_cache_purgeD_rng,		/* dcache_inv_range	*/
698129198Scognet	sa1_cache_cleanD_rng,		/* dcache_wb_range	*/
699129198Scognet
700129198Scognet	sa1_cache_purgeID,		/* idcache_wbinv_all	*/
701129198Scognet	sa1_cache_purgeID_rng,		/* idcache_wbinv_range	*/
702171618Scognet	cpufunc_nullop,			/* l2cache_wbinv_all	*/
703171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
704171781Scognet	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
705171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
706129198Scognet
707129198Scognet	/* Other functions */
708129198Scognet
709129198Scognet	sa11x0_drain_readbuf,		/* flush_prefetchbuf	*/
710129198Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
711129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
712129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
713129198Scognet
714129198Scognet	sa11x0_cpu_sleep,		/* sleep		*/
715129198Scognet
716129198Scognet	/* Soft functions */
717129198Scognet
718129198Scognet	cpufunc_null_fixup,		/* dataabt_fixup	*/
719129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
720129198Scognet
721129198Scognet	sa11x0_context_switch,		/* context_switch	*/
722129198Scognet
723129198Scognet	sa11x0_setup			/* cpu setup		*/
724236991Simp};
725129198Scognet#endif	/* CPU_SA1100 || CPU_SA1110 */
726129198Scognet
727129198Scognet#ifdef CPU_IXP12X0
728129198Scognetstruct cpu_functions ixp12x0_cpufuncs = {
729129198Scognet	/* CPU functions */
730129198Scognet
731129198Scognet	cpufunc_id,			/* id			*/
732129198Scognet	cpufunc_nullop,			/* cpwait		*/
733129198Scognet
734129198Scognet	/* MMU functions */
735129198Scognet
736129198Scognet	cpufunc_control,		/* control		*/
737129198Scognet	cpufunc_domains,		/* domain		*/
738129198Scognet	sa1_setttb,			/* setttb		*/
739129198Scognet	cpufunc_faultstatus,		/* faultstatus		*/
740129198Scognet	cpufunc_faultaddress,		/* faultaddress		*/
741129198Scognet
742129198Scognet	/* TLB functions */
743129198Scognet
744129198Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
745129198Scognet	sa1_tlb_flushID_SE,		/* tlb_flushID_SE	*/
746129198Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
747129198Scognet	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
748129198Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
749129198Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
750129198Scognet
751129198Scognet	/* Cache operations */
752129198Scognet
753129198Scognet	sa1_cache_syncI,		/* icache_sync_all	*/
754129198Scognet	sa1_cache_syncI_rng,		/* icache_sync_range	*/
755129198Scognet
756129198Scognet	sa1_cache_purgeD,		/* dcache_wbinv_all	*/
757129198Scognet	sa1_cache_purgeD_rng,		/* dcache_wbinv_range	*/
758129198Scognet/*XXX*/	sa1_cache_purgeD_rng,		/* dcache_inv_range	*/
759129198Scognet	sa1_cache_cleanD_rng,		/* dcache_wb_range	*/
760129198Scognet
761129198Scognet	sa1_cache_purgeID,		/* idcache_wbinv_all	*/
762129198Scognet	sa1_cache_purgeID_rng,		/* idcache_wbinv_range	*/
763171618Scognet	cpufunc_nullop,			/* l2cache_wbinv_all	*/
764171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
765171781Scognet	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
766171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
767129198Scognet
768129198Scognet	/* Other functions */
769129198Scognet
770129198Scognet	ixp12x0_drain_readbuf,			/* flush_prefetchbuf	*/
771129198Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
772129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
773129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
774129198Scognet
775129198Scognet	(void *)cpufunc_nullop,		/* sleep		*/
776129198Scognet
777129198Scognet	/* Soft functions */
778129198Scognet
779129198Scognet	cpufunc_null_fixup,		/* dataabt_fixup	*/
780129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
781129198Scognet
782129198Scognet	ixp12x0_context_switch,		/* context_switch	*/
783129198Scognet
784129198Scognet	ixp12x0_setup			/* cpu setup		*/
785236991Simp};
786129198Scognet#endif	/* CPU_IXP12X0 */
787129198Scognet
788129198Scognet#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
789161592Scognet  defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
790161592Scognet  defined(CPU_XSCALE_80219)
791161592Scognet
792129198Scognetstruct cpu_functions xscale_cpufuncs = {
793129198Scognet	/* CPU functions */
794129198Scognet
795129198Scognet	cpufunc_id,			/* id			*/
796129198Scognet	xscale_cpwait,			/* cpwait		*/
797129198Scognet
798129198Scognet	/* MMU functions */
799129198Scognet
800129198Scognet	xscale_control,			/* control		*/
801129198Scognet	cpufunc_domains,		/* domain		*/
802129198Scognet	xscale_setttb,			/* setttb		*/
803129198Scognet	cpufunc_faultstatus,		/* faultstatus		*/
804129198Scognet	cpufunc_faultaddress,		/* faultaddress		*/
805129198Scognet
806129198Scognet	/* TLB functions */
807129198Scognet
808129198Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
809129198Scognet	xscale_tlb_flushID_SE,		/* tlb_flushID_SE	*/
810129198Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
811129198Scognet	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
812129198Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
813129198Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
814129198Scognet
815129198Scognet	/* Cache operations */
816129198Scognet
817129198Scognet	xscale_cache_syncI,		/* icache_sync_all	*/
818129198Scognet	xscale_cache_syncI_rng,		/* icache_sync_range	*/
819129198Scognet
820129198Scognet	xscale_cache_purgeD,		/* dcache_wbinv_all	*/
821129198Scognet	xscale_cache_purgeD_rng,	/* dcache_wbinv_range	*/
822129198Scognet	xscale_cache_flushD_rng,	/* dcache_inv_range	*/
823129198Scognet	xscale_cache_cleanD_rng,	/* dcache_wb_range	*/
824129198Scognet
825129198Scognet	xscale_cache_purgeID,		/* idcache_wbinv_all	*/
826129198Scognet	xscale_cache_purgeID_rng,	/* idcache_wbinv_range	*/
827171618Scognet	cpufunc_nullop,			/* l2cache_wbinv_all 	*/
828171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
829171781Scognet	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
830171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
831129198Scognet
832129198Scognet	/* Other functions */
833129198Scognet
834129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
835129198Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
836129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
837129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
838129198Scognet
839129198Scognet	xscale_cpu_sleep,		/* sleep		*/
840129198Scognet
841129198Scognet	/* Soft functions */
842129198Scognet
843129198Scognet	cpufunc_null_fixup,		/* dataabt_fixup	*/
844129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
845129198Scognet
846129198Scognet	xscale_context_switch,		/* context_switch	*/
847129198Scognet
848129198Scognet	xscale_setup			/* cpu setup		*/
849129198Scognet};
850129198Scognet#endif
851161592Scognet/* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425
852161592Scognet   CPU_XSCALE_80219 */
853129198Scognet
854164080Scognet#ifdef CPU_XSCALE_81342
855164080Scognetstruct cpu_functions xscalec3_cpufuncs = {
856164080Scognet	/* CPU functions */
857164080Scognet
858164080Scognet	cpufunc_id,			/* id			*/
859164080Scognet	xscale_cpwait,			/* cpwait		*/
860164080Scognet
861164080Scognet	/* MMU functions */
862164080Scognet
863164080Scognet	xscale_control,			/* control		*/
864164080Scognet	cpufunc_domains,		/* domain		*/
865164080Scognet	xscalec3_setttb,		/* setttb		*/
866164080Scognet	cpufunc_faultstatus,		/* faultstatus		*/
867164080Scognet	cpufunc_faultaddress,		/* faultaddress		*/
868164080Scognet
869164080Scognet	/* TLB functions */
870164080Scognet
871164080Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
872164080Scognet	xscale_tlb_flushID_SE,		/* tlb_flushID_SE	*/
873164080Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
874164080Scognet	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
875164080Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
876164080Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
877164080Scognet
878164080Scognet	/* Cache operations */
879164080Scognet
880164080Scognet	xscalec3_cache_syncI,		/* icache_sync_all	*/
881171618Scognet	xscalec3_cache_syncI_rng,	/* icache_sync_range	*/
882164080Scognet
883164080Scognet	xscalec3_cache_purgeD,		/* dcache_wbinv_all	*/
884164080Scognet	xscalec3_cache_purgeD_rng,	/* dcache_wbinv_range	*/
885164080Scognet	xscale_cache_flushD_rng,	/* dcache_inv_range	*/
886164080Scognet	xscalec3_cache_cleanD_rng,	/* dcache_wb_range	*/
887164080Scognet
888171618Scognet	xscalec3_cache_purgeID,		/* idcache_wbinv_all	*/
889164080Scognet	xscalec3_cache_purgeID_rng,	/* idcache_wbinv_range	*/
890171618Scognet	xscalec3_l2cache_purge,		/* l2cache_wbinv_all	*/
891171618Scognet	xscalec3_l2cache_purge_rng,	/* l2cache_wbinv_range	*/
892171618Scognet	xscalec3_l2cache_flush_rng,	/* l2cache_inv_range	*/
893171618Scognet	xscalec3_l2cache_clean_rng,	/* l2cache_wb_range	*/
894164080Scognet
895164080Scognet	/* Other functions */
896164080Scognet
897164080Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
898164080Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
899164080Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
900164080Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
901164080Scognet
902164080Scognet	xscale_cpu_sleep,		/* sleep		*/
903164080Scognet
904164080Scognet	/* Soft functions */
905164080Scognet
906164080Scognet	cpufunc_null_fixup,		/* dataabt_fixup	*/
907164080Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
908164080Scognet
909164080Scognet	xscalec3_context_switch,	/* context_switch	*/
910164080Scognet
911164080Scognet	xscale_setup			/* cpu setup		*/
912164080Scognet};
913164080Scognet#endif /* CPU_XSCALE_81342 */
914201468Srpaulo
915201468Srpaulo
916207611Skevlo#if defined(CPU_FA526) || defined(CPU_FA626TE)
917201468Srpaulostruct cpu_functions fa526_cpufuncs = {
918201468Srpaulo	/* CPU functions */
919201468Srpaulo
920207611Skevlo	cpufunc_id,			/* id			*/
921207611Skevlo	cpufunc_nullop,			/* cpwait		*/
922201468Srpaulo
923201468Srpaulo	/* MMU functions */
924201468Srpaulo
925207611Skevlo	cpufunc_control,		/* control		*/
926207611Skevlo	cpufunc_domains,		/* domain		*/
927207611Skevlo	fa526_setttb,			/* setttb		*/
928207611Skevlo	cpufunc_faultstatus,		/* faultstatus		*/
929207611Skevlo	cpufunc_faultaddress,		/* faultaddress		*/
930201468Srpaulo
931201468Srpaulo	/* TLB functions */
932201468Srpaulo
933207611Skevlo	armv4_tlb_flushID,		/* tlb_flushID		*/
934207611Skevlo	fa526_tlb_flushID_SE,		/* tlb_flushID_SE	*/
935207611Skevlo	armv4_tlb_flushI,		/* tlb_flushI		*/
936207611Skevlo	fa526_tlb_flushI_SE,		/* tlb_flushI_SE	*/
937207611Skevlo	armv4_tlb_flushD,		/* tlb_flushD		*/
938207611Skevlo	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
939201468Srpaulo
940201468Srpaulo	/* Cache operations */
941201468Srpaulo
942207611Skevlo	fa526_icache_sync_all,		/* icache_sync_all	*/
943207611Skevlo	fa526_icache_sync_range,	/* icache_sync_range	*/
944201468Srpaulo
945207611Skevlo	fa526_dcache_wbinv_all,		/* dcache_wbinv_all	*/
946207611Skevlo	fa526_dcache_wbinv_range,	/* dcache_wbinv_range	*/
947207611Skevlo	fa526_dcache_inv_range,		/* dcache_inv_range	*/
948207611Skevlo	fa526_dcache_wb_range,		/* dcache_wb_range	*/
949201468Srpaulo
950207611Skevlo	fa526_idcache_wbinv_all,	/* idcache_wbinv_all	*/
951207611Skevlo	fa526_idcache_wbinv_range,	/* idcache_wbinv_range	*/
952207611Skevlo	cpufunc_nullop,			/* l2cache_wbinv_all	*/
953207611Skevlo	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
954207611Skevlo	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
955207611Skevlo	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
956201468Srpaulo
957201468Srpaulo	/* Other functions */
958201468Srpaulo
959207611Skevlo	fa526_flush_prefetchbuf,	/* flush_prefetchbuf	*/
960207611Skevlo	armv4_drain_writebuf,		/* drain_writebuf	*/
961207611Skevlo	cpufunc_nullop,			/* flush_brnchtgt_C	*/
962207611Skevlo	fa526_flush_brnchtgt_E,		/* flush_brnchtgt_E	*/
963201468Srpaulo
964207611Skevlo	fa526_cpu_sleep,		/* sleep		*/
965201468Srpaulo
966201468Srpaulo	/* Soft functions */
967201468Srpaulo
968207611Skevlo	cpufunc_null_fixup,		/* dataabt_fixup	*/
969207611Skevlo	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
970201468Srpaulo
971207611Skevlo	fa526_context_switch,		/* context_switch	*/
972201468Srpaulo
973207611Skevlo	fa526_setup			/* cpu setup 		*/
974236991Simp};
975207611Skevlo#endif	/* CPU_FA526 || CPU_FA626TE */
976201468Srpaulo
977244480Sgonzo#if defined(CPU_ARM1136)
978244480Sgonzostruct cpu_functions arm1136_cpufuncs = {
979239701Sgonzo	/* CPU functions */
980239701Sgonzo
981239701Sgonzo	cpufunc_id,                     /* id                   */
982244480Sgonzo	cpufunc_nullop,                 /* cpwait               */
983239701Sgonzo
984239701Sgonzo	/* MMU functions */
985239701Sgonzo
986239701Sgonzo	cpufunc_control,                /* control              */
987239701Sgonzo	cpufunc_domains,                /* Domain               */
988244480Sgonzo	arm11x6_setttb,                 /* Setttb               */
989239701Sgonzo	cpufunc_faultstatus,            /* Faultstatus          */
990239701Sgonzo	cpufunc_faultaddress,           /* Faultaddress         */
991239701Sgonzo
992239701Sgonzo	/* TLB functions */
993239701Sgonzo
994239701Sgonzo	arm11_tlb_flushID,              /* tlb_flushID          */
995239701Sgonzo	arm11_tlb_flushID_SE,           /* tlb_flushID_SE       */
996239701Sgonzo	arm11_tlb_flushI,               /* tlb_flushI           */
997239701Sgonzo	arm11_tlb_flushI_SE,            /* tlb_flushI_SE        */
998239701Sgonzo	arm11_tlb_flushD,               /* tlb_flushD           */
999239701Sgonzo	arm11_tlb_flushD_SE,            /* tlb_flushD_SE        */
1000239701Sgonzo
1001239701Sgonzo	/* Cache operations */
1002239701Sgonzo
1003244480Sgonzo	arm11x6_icache_sync_all,        /* icache_sync_all      */
1004244480Sgonzo	arm11x6_icache_sync_range,      /* icache_sync_range    */
1005239701Sgonzo
1006244480Sgonzo	arm11x6_dcache_wbinv_all,       /* dcache_wbinv_all     */
1007239701Sgonzo	armv6_dcache_wbinv_range,       /* dcache_wbinv_range   */
1008239701Sgonzo	armv6_dcache_inv_range,         /* dcache_inv_range     */
1009239701Sgonzo	armv6_dcache_wb_range,          /* dcache_wb_range      */
1010239701Sgonzo
1011244480Sgonzo	arm11x6_idcache_wbinv_all,      /* idcache_wbinv_all    */
1012244480Sgonzo	arm11x6_idcache_wbinv_range,    /* idcache_wbinv_range  */
1013239701Sgonzo
1014244480Sgonzo	(void *)cpufunc_nullop,         /* l2cache_wbinv_all    */
1015239701Sgonzo	(void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
1016239701Sgonzo	(void *)cpufunc_nullop,         /* l2cache_inv_range    */
1017239701Sgonzo	(void *)cpufunc_nullop,         /* l2cache_wb_range     */
1018239701Sgonzo
1019239701Sgonzo	/* Other functions */
1020239701Sgonzo
1021244480Sgonzo	arm11x6_flush_prefetchbuf,      /* flush_prefetchbuf    */
1022239701Sgonzo	arm11_drain_writebuf,           /* drain_writebuf       */
1023239701Sgonzo	cpufunc_nullop,                 /* flush_brnchtgt_C     */
1024239701Sgonzo	(void *)cpufunc_nullop,         /* flush_brnchtgt_E     */
1025239701Sgonzo
1026244480Sgonzo	arm11_sleep,                  	/* sleep                */
1027239701Sgonzo
1028239701Sgonzo	/* Soft functions */
1029239701Sgonzo
1030239701Sgonzo	cpufunc_null_fixup,             /* dataabt_fixup        */
1031239701Sgonzo	cpufunc_null_fixup,             /* prefetchabt_fixup    */
1032239701Sgonzo
1033239701Sgonzo	arm11_context_switch,           /* context_switch       */
1034239701Sgonzo
1035244480Sgonzo	arm11x6_setup                   /* cpu setup            */
1036239701Sgonzo};
1037244480Sgonzo#endif /* CPU_ARM1136 */
1038244480Sgonzo#if defined(CPU_ARM1176)
1039244480Sgonzostruct cpu_functions arm1176_cpufuncs = {
1040244480Sgonzo	/* CPU functions */
1041244480Sgonzo
1042244480Sgonzo	cpufunc_id,                     /* id                   */
1043244480Sgonzo	cpufunc_nullop,                 /* cpwait               */
1044244480Sgonzo
1045244480Sgonzo	/* MMU functions */
1046244480Sgonzo
1047244480Sgonzo	cpufunc_control,                /* control              */
1048244480Sgonzo	cpufunc_domains,                /* Domain               */
1049244480Sgonzo	arm11x6_setttb,                 /* Setttb               */
1050244480Sgonzo	cpufunc_faultstatus,            /* Faultstatus          */
1051244480Sgonzo	cpufunc_faultaddress,           /* Faultaddress         */
1052244480Sgonzo
1053244480Sgonzo	/* TLB functions */
1054244480Sgonzo
1055244480Sgonzo	arm11_tlb_flushID,              /* tlb_flushID          */
1056244480Sgonzo	arm11_tlb_flushID_SE,           /* tlb_flushID_SE       */
1057244480Sgonzo	arm11_tlb_flushI,               /* tlb_flushI           */
1058244480Sgonzo	arm11_tlb_flushI_SE,            /* tlb_flushI_SE        */
1059244480Sgonzo	arm11_tlb_flushD,               /* tlb_flushD           */
1060244480Sgonzo	arm11_tlb_flushD_SE,            /* tlb_flushD_SE        */
1061244480Sgonzo
1062244480Sgonzo	/* Cache operations */
1063244480Sgonzo
1064244480Sgonzo	arm11x6_icache_sync_all,        /* icache_sync_all      */
1065244480Sgonzo	arm11x6_icache_sync_range,      /* icache_sync_range    */
1066244480Sgonzo
1067244480Sgonzo	arm11x6_dcache_wbinv_all,       /* dcache_wbinv_all     */
1068244480Sgonzo	armv6_dcache_wbinv_range,       /* dcache_wbinv_range   */
1069244480Sgonzo	armv6_dcache_inv_range,         /* dcache_inv_range     */
1070244480Sgonzo	armv6_dcache_wb_range,          /* dcache_wb_range      */
1071244480Sgonzo
1072244480Sgonzo	arm11x6_idcache_wbinv_all,      /* idcache_wbinv_all    */
1073244480Sgonzo	arm11x6_idcache_wbinv_range,    /* idcache_wbinv_range  */
1074244480Sgonzo
1075244480Sgonzo	(void *)cpufunc_nullop,         /* l2cache_wbinv_all    */
1076244480Sgonzo	(void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
1077244480Sgonzo	(void *)cpufunc_nullop,         /* l2cache_inv_range    */
1078244480Sgonzo	(void *)cpufunc_nullop,         /* l2cache_wb_range     */
1079244480Sgonzo
1080244480Sgonzo	/* Other functions */
1081244480Sgonzo
1082244480Sgonzo	arm11x6_flush_prefetchbuf,      /* flush_prefetchbuf    */
1083244480Sgonzo	arm11_drain_writebuf,           /* drain_writebuf       */
1084244480Sgonzo	cpufunc_nullop,                 /* flush_brnchtgt_C     */
1085244480Sgonzo	(void *)cpufunc_nullop,         /* flush_brnchtgt_E     */
1086244480Sgonzo
1087244480Sgonzo	arm11x6_sleep,                  /* sleep                */
1088244480Sgonzo
1089244480Sgonzo	/* Soft functions */
1090244480Sgonzo
1091244480Sgonzo	cpufunc_null_fixup,             /* dataabt_fixup        */
1092244480Sgonzo	cpufunc_null_fixup,             /* prefetchabt_fixup    */
1093244480Sgonzo
1094244480Sgonzo	arm11_context_switch,           /* context_switch       */
1095244480Sgonzo
1096244480Sgonzo	arm11x6_setup                   /* cpu setup            */
1097244480Sgonzo};
1098244480Sgonzo#endif /*CPU_ARM1176 */
1099239701Sgonzo
1100239268Sgonzo#if defined(CPU_CORTEXA)
1101239268Sgonzostruct cpu_functions cortexa_cpufuncs = {
1102239268Sgonzo	/* CPU functions */
1103239268Sgonzo
1104239268Sgonzo	cpufunc_id,                     /* id                   */
1105239268Sgonzo	cpufunc_nullop,                 /* cpwait               */
1106239268Sgonzo
1107239268Sgonzo	/* MMU functions */
1108239268Sgonzo
1109239268Sgonzo	cpufunc_control,                /* control              */
1110239268Sgonzo	cpufunc_domains,                /* Domain               */
1111239268Sgonzo	armv7_setttb,                   /* Setttb               */
1112239268Sgonzo	cpufunc_faultstatus,            /* Faultstatus          */
1113239268Sgonzo	cpufunc_faultaddress,           /* Faultaddress         */
1114239268Sgonzo
1115239268Sgonzo	/* TLB functions */
1116239268Sgonzo
1117243024Scognet	armv7_tlb_flushID,              /* tlb_flushID          */
1118239268Sgonzo	armv7_tlb_flushID_SE,           /* tlb_flushID_SE       */
1119239268Sgonzo	arm11_tlb_flushI,               /* tlb_flushI           */
1120239268Sgonzo	arm11_tlb_flushI_SE,            /* tlb_flushI_SE        */
1121239268Sgonzo	arm11_tlb_flushD,               /* tlb_flushD           */
1122239268Sgonzo	arm11_tlb_flushD_SE,            /* tlb_flushD_SE        */
1123239268Sgonzo
1124239268Sgonzo	/* Cache operations */
1125239268Sgonzo
1126239268Sgonzo	armv7_idcache_wbinv_all,         /* icache_sync_all      */
1127239268Sgonzo	armv7_icache_sync_range,        /* icache_sync_range    */
1128239268Sgonzo
1129239268Sgonzo	armv7_dcache_wbinv_all,         /* dcache_wbinv_all     */
1130239268Sgonzo	armv7_dcache_wbinv_range,       /* dcache_wbinv_range   */
1131239268Sgonzo	armv7_dcache_inv_range,         /* dcache_inv_range     */
1132239268Sgonzo	armv7_dcache_wb_range,          /* dcache_wb_range      */
1133239268Sgonzo
1134239268Sgonzo	armv7_idcache_wbinv_all,        /* idcache_wbinv_all    */
1135239268Sgonzo	armv7_idcache_wbinv_range,      /* idcache_wbinv_range  */
1136239268Sgonzo
1137243026Scognet	/*
1138243026Scognet	 * Note: For CPUs using the PL310 the L2 ops are filled in when the
1139239268Sgonzo	 * L2 cache controller is actually enabled.
1140239268Sgonzo	 */
1141239268Sgonzo	cpufunc_nullop,                 /* l2cache_wbinv_all    */
1142239268Sgonzo	(void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
1143239268Sgonzo	(void *)cpufunc_nullop,         /* l2cache_inv_range    */
1144239268Sgonzo	(void *)cpufunc_nullop,         /* l2cache_wb_range     */
1145239268Sgonzo
1146239268Sgonzo	/* Other functions */
1147239268Sgonzo
1148239268Sgonzo	cpufunc_nullop,                 /* flush_prefetchbuf    */
1149245478Scognet	armv7_drain_writebuf,           /* drain_writebuf       */
1150239268Sgonzo	cpufunc_nullop,                 /* flush_brnchtgt_C     */
1151239268Sgonzo	(void *)cpufunc_nullop,         /* flush_brnchtgt_E     */
1152239268Sgonzo
1153239268Sgonzo	arm11_sleep,                    /* sleep                */
1154239268Sgonzo
1155239268Sgonzo	/* Soft functions */
1156239268Sgonzo
1157239268Sgonzo	cpufunc_null_fixup,             /* dataabt_fixup        */
1158239268Sgonzo	cpufunc_null_fixup,             /* prefetchabt_fixup    */
1159239268Sgonzo
1160245478Scognet	armv7_context_switch,           /* context_switch       */
1161239268Sgonzo
1162239268Sgonzo	cortexa_setup                     /* cpu setup            */
1163239268Sgonzo};
1164239268Sgonzo#endif /* CPU_CORTEXA */
1165201468Srpaulo
1166129198Scognet/*
1167129198Scognet * Global constants also used by locore.s
1168129198Scognet */
1169129198Scognet
1170129198Scognetstruct cpu_functions cpufuncs;
1171129198Scognetu_int cputype;
1172129198Scognetu_int cpu_reset_needs_v4_MMU_disable;	/* flag used in locore.s */
1173129198Scognet
1174207611Skevlo#if defined(CPU_ARM7TDMI) || defined(CPU_ARM8) || defined(CPU_ARM9) ||	\
1175244480Sgonzo  defined (CPU_ARM9E) || defined (CPU_ARM10) || defined (CPU_ARM1136) ||	\
1176244480Sgonzo  defined(CPU_ARM1176) || defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) ||		\
1177207611Skevlo  defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) ||		\
1178239268Sgonzo  defined(CPU_FA526) || defined(CPU_FA626TE) || defined(CPU_MV_PJ4B) ||			\
1179239268Sgonzo  defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \
1180239268Sgonzo  defined(CPU_CORTEXA)
1181161592Scognet
1182137498Strhodesstatic void get_cachetype_cp15(void);
1183129198Scognet
1184129198Scognet/* Additional cache information local to this file.  Log2 of some of the
1185129198Scognet   above numbers.  */
1186129198Scognetstatic int	arm_dcache_l2_nsets;
1187129198Scognetstatic int	arm_dcache_l2_assoc;
1188129198Scognetstatic int	arm_dcache_l2_linesize;
1189129198Scognet
1190129198Scognetstatic void
1191129198Scognetget_cachetype_cp15()
1192129198Scognet{
1193239268Sgonzo	u_int ctype, isize, dsize, cpuid;
1194239268Sgonzo	u_int clevel, csize, i, sel;
1195129198Scognet	u_int multiplier;
1196239268Sgonzo	u_char type;
1197129198Scognet
1198129198Scognet	__asm __volatile("mrc p15, 0, %0, c0, c0, 1"
1199129198Scognet		: "=r" (ctype));
1200129198Scognet
1201239268Sgonzo	cpuid = cpufunc_id();
1202129198Scognet	/*
1203129198Scognet	 * ...and thus spake the ARM ARM:
1204129198Scognet	 *
1205129198Scognet	 * If an <opcode2> value corresponding to an unimplemented or
1206129198Scognet	 * reserved ID register is encountered, the System Control
1207129198Scognet	 * processor returns the value of the main ID register.
1208129198Scognet	 */
1209239268Sgonzo	if (ctype == cpuid)
1210129198Scognet		goto out;
1211129198Scognet
1212239268Sgonzo	if (CPU_CT_FORMAT(ctype) == CPU_CT_ARMV7) {
1213239268Sgonzo		__asm __volatile("mrc p15, 1, %0, c0, c0, 1"
1214239268Sgonzo		    : "=r" (clevel));
1215239268Sgonzo		arm_cache_level = clevel;
1216239268Sgonzo		arm_cache_loc = CPU_CLIDR_LOC(arm_cache_level);
1217239268Sgonzo		i = 0;
1218239268Sgonzo		while ((type = (clevel & 0x7)) && i < 7) {
1219239268Sgonzo			if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
1220239268Sgonzo			    type == CACHE_SEP_CACHE) {
1221239268Sgonzo				sel = i << 1;
1222239268Sgonzo				__asm __volatile("mcr p15, 2, %0, c0, c0, 0"
1223239268Sgonzo				    : : "r" (sel));
1224239268Sgonzo				__asm __volatile("mrc p15, 1, %0, c0, c0, 0"
1225239268Sgonzo				    : "=r" (csize));
1226239268Sgonzo				arm_cache_type[sel] = csize;
1227239268Sgonzo				arm_dcache_align = 1 <<
1228239268Sgonzo				    (CPUV7_CT_xSIZE_LEN(csize) + 4);
1229239268Sgonzo				arm_dcache_align_mask = arm_dcache_align - 1;
1230239268Sgonzo			}
1231239268Sgonzo			if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
1232239268Sgonzo				sel = (i << 1) | 1;
1233239268Sgonzo				__asm __volatile("mcr p15, 2, %0, c0, c0, 0"
1234239268Sgonzo				    : : "r" (sel));
1235239268Sgonzo				__asm __volatile("mrc p15, 1, %0, c0, c0, 0"
1236239268Sgonzo				    : "=r" (csize));
1237239268Sgonzo				arm_cache_type[sel] = csize;
1238239268Sgonzo			}
1239239268Sgonzo			i++;
1240239268Sgonzo			clevel >>= 3;
1241239268Sgonzo		}
1242239268Sgonzo	} else {
1243239268Sgonzo		if ((ctype & CPU_CT_S) == 0)
1244239268Sgonzo			arm_pcache_unified = 1;
1245129198Scognet
1246239268Sgonzo		/*
1247239268Sgonzo		 * If you want to know how this code works, go read the ARM ARM.
1248239268Sgonzo		 */
1249129198Scognet
1250239268Sgonzo		arm_pcache_type = CPU_CT_CTYPE(ctype);
1251129198Scognet
1252239268Sgonzo		if (arm_pcache_unified == 0) {
1253239268Sgonzo			isize = CPU_CT_ISIZE(ctype);
1254239268Sgonzo			multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2;
1255239268Sgonzo			arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3);
1256239268Sgonzo			if (CPU_CT_xSIZE_ASSOC(isize) == 0) {
1257239268Sgonzo				if (isize & CPU_CT_xSIZE_M)
1258239268Sgonzo					arm_picache_line_size = 0; /* not present */
1259239268Sgonzo				else
1260239268Sgonzo					arm_picache_ways = 1;
1261239268Sgonzo			} else {
1262239268Sgonzo				arm_picache_ways = multiplier <<
1263239268Sgonzo				    (CPU_CT_xSIZE_ASSOC(isize) - 1);
1264239268Sgonzo			}
1265239268Sgonzo			arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
1266239268Sgonzo		}
1267239268Sgonzo
1268239268Sgonzo		dsize = CPU_CT_DSIZE(ctype);
1269239268Sgonzo		multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
1270239268Sgonzo		arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
1271239268Sgonzo		if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
1272239268Sgonzo			if (dsize & CPU_CT_xSIZE_M)
1273239268Sgonzo				arm_pdcache_line_size = 0; /* not present */
1274129198Scognet			else
1275239268Sgonzo				arm_pdcache_ways = 1;
1276129198Scognet		} else {
1277239268Sgonzo			arm_pdcache_ways = multiplier <<
1278239268Sgonzo			    (CPU_CT_xSIZE_ASSOC(dsize) - 1);
1279129198Scognet		}
1280239268Sgonzo		arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
1281129198Scognet
1282239268Sgonzo		arm_dcache_align = arm_pdcache_line_size;
1283129198Scognet
1284239268Sgonzo		arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2;
1285239268Sgonzo		arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3;
1286239268Sgonzo		arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) -
1287239268Sgonzo		    CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize);
1288129198Scognet
1289239268Sgonzo	out:
1290239268Sgonzo		arm_dcache_align_mask = arm_dcache_align - 1;
1291239268Sgonzo	}
1292129198Scognet}
1293129198Scognet#endif /* ARM7TDMI || ARM8 || ARM9 || XSCALE */
1294129198Scognet
1295146619Scognet#if defined(CPU_SA110) || defined(CPU_SA1100) || defined(CPU_SA1110) || \
1296146619Scognet    defined(CPU_IXP12X0)
1297129198Scognet/* Cache information for CPUs without cache type registers. */
1298129198Scognetstruct cachetab {
1299129198Scognet	u_int32_t ct_cpuid;
1300129198Scognet	int	ct_pcache_type;
1301129198Scognet	int	ct_pcache_unified;
1302129198Scognet	int	ct_pdcache_size;
1303129198Scognet	int	ct_pdcache_line_size;
1304129198Scognet	int	ct_pdcache_ways;
1305129198Scognet	int	ct_picache_size;
1306129198Scognet	int	ct_picache_line_size;
1307129198Scognet	int	ct_picache_ways;
1308129198Scognet};
1309129198Scognet
1310129198Scognetstruct cachetab cachetab[] = {
1311129198Scognet    /* cpuid,           cache type,       u,  dsiz, ls, wy,  isiz, ls, wy */
1312129198Scognet    /* XXX is this type right for SA-1? */
1313129198Scognet    { CPU_ID_SA110,	CPU_CT_CTYPE_WB1, 0, 16384, 32, 32, 16384, 32, 32 },
1314129198Scognet    { CPU_ID_SA1100,	CPU_CT_CTYPE_WB1, 0,  8192, 32, 32, 16384, 32, 32 },
1315129198Scognet    { CPU_ID_SA1110,	CPU_CT_CTYPE_WB1, 0,  8192, 32, 32, 16384, 32, 32 },
1316129198Scognet    { CPU_ID_IXP1200,	CPU_CT_CTYPE_WB1, 0, 16384, 32, 32, 16384, 32, 32 }, /* XXX */
1317129198Scognet    { 0, 0, 0, 0, 0, 0, 0, 0}
1318129198Scognet};
1319129198Scognet
1320137498Strhodesstatic void get_cachetype_table(void);
1321129198Scognet
1322129198Scognetstatic void
1323129198Scognetget_cachetype_table()
1324129198Scognet{
1325129198Scognet	int i;
1326129198Scognet	u_int32_t cpuid = cpufunc_id();
1327129198Scognet
1328129198Scognet	for (i = 0; cachetab[i].ct_cpuid != 0; i++) {
1329129198Scognet		if (cachetab[i].ct_cpuid == (cpuid & CPU_ID_CPU_MASK)) {
1330129198Scognet			arm_pcache_type = cachetab[i].ct_pcache_type;
1331129198Scognet			arm_pcache_unified = cachetab[i].ct_pcache_unified;
1332129198Scognet			arm_pdcache_size = cachetab[i].ct_pdcache_size;
1333129198Scognet			arm_pdcache_line_size =
1334129198Scognet			    cachetab[i].ct_pdcache_line_size;
1335129198Scognet			arm_pdcache_ways = cachetab[i].ct_pdcache_ways;
1336129198Scognet			arm_picache_size = cachetab[i].ct_picache_size;
1337129198Scognet			arm_picache_line_size =
1338129198Scognet			    cachetab[i].ct_picache_line_size;
1339129198Scognet			arm_picache_ways = cachetab[i].ct_picache_ways;
1340129198Scognet		}
1341129198Scognet	}
1342129198Scognet	arm_dcache_align = arm_pdcache_line_size;
1343129198Scognet
1344129198Scognet	arm_dcache_align_mask = arm_dcache_align - 1;
1345129198Scognet}
1346129198Scognet
1347146619Scognet#endif /* SA110 || SA1100 || SA1111 || IXP12X0 */
1348129198Scognet
1349129198Scognet/*
1350129198Scognet * Cannot panic here as we may not have a console yet ...
1351129198Scognet */
1352129198Scognet
1353129198Scognetint
1354129198Scognetset_cpufuncs()
1355129198Scognet{
1356129198Scognet	cputype = cpufunc_id();
1357129198Scognet	cputype &= CPU_ID_CPU_MASK;
1358129198Scognet
1359129198Scognet	/*
1360129198Scognet	 * NOTE: cpu_do_powersave defaults to off.  If we encounter a
1361129198Scognet	 * CPU type where we want to use it by default, then we set it.
1362129198Scognet	 */
1363129198Scognet
1364129198Scognet#ifdef CPU_ARM7TDMI
1365129198Scognet	if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD &&
1366129198Scognet	    CPU_ID_IS7(cputype) &&
1367129198Scognet	    (cputype & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V4T) {
1368129198Scognet		cpufuncs = arm7tdmi_cpufuncs;
1369129198Scognet		cpu_reset_needs_v4_MMU_disable = 0;
1370129198Scognet		get_cachetype_cp15();
1371129198Scognet		pmap_pte_init_generic();
1372166655Scognet		goto out;
1373129198Scognet	}
1374129198Scognet#endif
1375129198Scognet#ifdef CPU_ARM8
1376129198Scognet	if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD &&
1377129198Scognet	    (cputype & 0x0000f000) == 0x00008000) {
1378129198Scognet		cpufuncs = arm8_cpufuncs;
1379129198Scognet		cpu_reset_needs_v4_MMU_disable = 0;	/* XXX correct? */
1380129198Scognet		get_cachetype_cp15();
1381129198Scognet		pmap_pte_init_arm8();
1382166655Scognet		goto out;
1383129198Scognet	}
1384129198Scognet#endif	/* CPU_ARM8 */
1385129198Scognet#ifdef CPU_ARM9
1386129198Scognet	if (((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD ||
1387129198Scognet	     (cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_TI) &&
1388129198Scognet	    (cputype & 0x0000f000) == 0x00009000) {
1389129198Scognet		cpufuncs = arm9_cpufuncs;
1390129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* V4 or higher */
1391129198Scognet		get_cachetype_cp15();
1392146605Scognet		arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize;
1393146605Scognet		arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize +
1394146605Scognet		    arm_dcache_l2_nsets)) - arm9_dcache_sets_inc;
1395146605Scognet		arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc);
1396146605Scognet		arm9_dcache_index_max = 0U - arm9_dcache_index_inc;
1397137270Scognet#ifdef ARM9_CACHE_WRITE_THROUGH
1398129198Scognet		pmap_pte_init_arm9();
1399137270Scognet#else
1400137270Scognet		pmap_pte_init_generic();
1401137270Scognet#endif
1402166655Scognet		goto out;
1403129198Scognet	}
1404129198Scognet#endif /* CPU_ARM9 */
1405172738Simp#if defined(CPU_ARM9E) || defined(CPU_ARM10)
1406239268Sgonzo	if (cputype == CPU_ID_MV88FR131 || cputype == CPU_ID_MV88FR571_VD ||
1407183835Sraj	    cputype == CPU_ID_MV88FR571_41) {
1408239268Sgonzo		uint32_t sheeva_ctrl;
1409183835Sraj
1410239268Sgonzo		sheeva_ctrl = (MV_DC_STREAM_ENABLE | MV_BTB_DISABLE |
1411239268Sgonzo		    MV_L2_ENABLE);
1412239268Sgonzo		/*
1413239268Sgonzo		 * Workaround for Marvell MV78100 CPU: Cache prefetch
1414239268Sgonzo		 * mechanism may affect the cache coherency validity,
1415239268Sgonzo		 * so it needs to be disabled.
1416239268Sgonzo		 *
1417239268Sgonzo		 * Refer to errata document MV-S501058-00C.pdf (p. 3.1
1418239268Sgonzo		 * L2 Prefetching Mechanism) for details.
1419239268Sgonzo		 */
1420239268Sgonzo		if (cputype == CPU_ID_MV88FR571_VD ||
1421239268Sgonzo		    cputype == CPU_ID_MV88FR571_41)
1422239268Sgonzo			sheeva_ctrl |= MV_L2_PREFETCH_DISABLE;
1423212825Smav
1424239268Sgonzo		sheeva_control_ext(0xffffffff & ~MV_WA_ENABLE, sheeva_ctrl);
1425183835Sraj
1426239268Sgonzo		cpufuncs = sheeva_cpufuncs;
1427172738Simp		get_cachetype_cp15();
1428172738Simp		pmap_pte_init_generic();
1429174058Scognet		goto out;
1430239268Sgonzo	} else if (cputype == CPU_ID_ARM926EJS || cputype == CPU_ID_ARM1026EJS) {
1431239268Sgonzo		cpufuncs = armv5_ec_cpufuncs;
1432239268Sgonzo		get_cachetype_cp15();
1433239268Sgonzo		pmap_pte_init_generic();
1434239268Sgonzo		goto out;
1435172738Simp	}
1436172738Simp#endif /* CPU_ARM9E || CPU_ARM10 */
1437129198Scognet#ifdef CPU_ARM10
1438129198Scognet	if (/* cputype == CPU_ID_ARM1020T || */
1439129198Scognet	    cputype == CPU_ID_ARM1020E) {
1440129198Scognet		/*
1441129198Scognet		 * Select write-through cacheing (this isn't really an
1442129198Scognet		 * option on ARM1020T).
1443129198Scognet		 */
1444129198Scognet		cpufuncs = arm10_cpufuncs;
1445129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* V4 or higher */
1446129198Scognet		get_cachetype_cp15();
1447129198Scognet		arm10_dcache_sets_inc = 1U << arm_dcache_l2_linesize;
1448236991Simp		arm10_dcache_sets_max =
1449129198Scognet		    (1U << (arm_dcache_l2_linesize + arm_dcache_l2_nsets)) -
1450129198Scognet		    arm10_dcache_sets_inc;
1451129198Scognet		arm10_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc);
1452129198Scognet		arm10_dcache_index_max = 0U - arm10_dcache_index_inc;
1453129198Scognet		pmap_pte_init_generic();
1454166655Scognet		goto out;
1455129198Scognet	}
1456129198Scognet#endif /* CPU_ARM10 */
1457244480Sgonzo#if defined(CPU_ARM1136) || defined(CPU_ARM1176)
1458244480Sgonzo	if (cputype == CPU_ID_ARM1136JS
1459244480Sgonzo	    || cputype == CPU_ID_ARM1136JSR1
1460244480Sgonzo	    || cputype == CPU_ID_ARM1176JZS) {
1461244480Sgonzo#ifdef CPU_ARM1136
1462244480Sgonzo		if (cputype == CPU_ID_ARM1136JS
1463244480Sgonzo		    || cputype == CPU_ID_ARM1136JSR1)
1464244480Sgonzo			cpufuncs = arm1136_cpufuncs;
1465244480Sgonzo#endif
1466244480Sgonzo#ifdef CPU_ARM1176
1467244480Sgonzo		if (cputype == CPU_ID_ARM1176JZS)
1468244480Sgonzo			cpufuncs = arm1176_cpufuncs;
1469244480Sgonzo#endif
1470244480Sgonzo		cpu_reset_needs_v4_MMU_disable = 1;     /* V4 or higher */
1471244480Sgonzo		get_cachetype_cp15();
1472239701Sgonzo
1473244480Sgonzo		pmap_pte_init_mmu_v6();
1474244480Sgonzo
1475244480Sgonzo		goto out;
1476244480Sgonzo	}
1477244480Sgonzo#endif /* CPU_ARM1136 || CPU_ARM1176 */
1478239268Sgonzo#ifdef CPU_CORTEXA
1479256629Sbr	if (cputype == CPU_ID_CORTEXA5 ||
1480256629Sbr	    cputype == CPU_ID_CORTEXA7 ||
1481253857Sganbold	    cputype == CPU_ID_CORTEXA8R1 ||
1482239268Sgonzo	    cputype == CPU_ID_CORTEXA8R2 ||
1483239268Sgonzo	    cputype == CPU_ID_CORTEXA8R3 ||
1484239268Sgonzo	    cputype == CPU_ID_CORTEXA9R1 ||
1485249999Swkoszek	    cputype == CPU_ID_CORTEXA9R2 ||
1486252361Sray	    cputype == CPU_ID_CORTEXA9R3 ||
1487252361Sray	    cputype == CPU_ID_CORTEXA15 ) {
1488239268Sgonzo		cpufuncs = cortexa_cpufuncs;
1489239268Sgonzo		cpu_reset_needs_v4_MMU_disable = 1;     /* V4 or higher */
1490239268Sgonzo		get_cachetype_cp15();
1491239268Sgonzo
1492239268Sgonzo		pmap_pte_init_mmu_v6();
1493239268Sgonzo		/* Use powersave on this CPU. */
1494239268Sgonzo		cpu_do_powersave = 1;
1495239268Sgonzo		goto out;
1496239268Sgonzo	}
1497239268Sgonzo#endif /* CPU_CORTEXA */
1498239268Sgonzo
1499239268Sgonzo#if defined(CPU_MV_PJ4B)
1500239268Sgonzo	if (cputype == CPU_ID_MV88SV581X_V6 ||
1501239268Sgonzo	    cputype == CPU_ID_MV88SV581X_V7 ||
1502240486Sgber	    cputype == CPU_ID_MV88SV584X_V7 ||
1503239268Sgonzo	    cputype == CPU_ID_ARM_88SV581X_V6 ||
1504239268Sgonzo	    cputype == CPU_ID_ARM_88SV581X_V7) {
1505239268Sgonzo		if (cpu_pfr(0) & ARM_PFR0_THUMBEE_MASK)
1506239268Sgonzo			cpufuncs = pj4bv7_cpufuncs;
1507239268Sgonzo		else
1508239268Sgonzo			cpufuncs = pj4bv6_cpufuncs;
1509239268Sgonzo
1510239268Sgonzo		get_cachetype_cp15();
1511239268Sgonzo		pmap_pte_init_mmu_v6();
1512239268Sgonzo		goto out;
1513240486Sgber	} else if (cputype == CPU_ID_ARM_88SV584X_V6 ||
1514240486Sgber	    cputype == CPU_ID_MV88SV584X_V6) {
1515239268Sgonzo		cpufuncs = pj4bv6_cpufuncs;
1516239268Sgonzo		get_cachetype_cp15();
1517239268Sgonzo		pmap_pte_init_mmu_v6();
1518239268Sgonzo		goto out;
1519239268Sgonzo	}
1520239268Sgonzo
1521239268Sgonzo#endif /* CPU_MV_PJ4B */
1522129198Scognet#ifdef CPU_SA110
1523129198Scognet	if (cputype == CPU_ID_SA110) {
1524129198Scognet		cpufuncs = sa110_cpufuncs;
1525129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* SA needs it */
1526129198Scognet		get_cachetype_table();
1527129198Scognet		pmap_pte_init_sa1();
1528166655Scognet		goto out;
1529129198Scognet	}
1530129198Scognet#endif	/* CPU_SA110 */
1531129198Scognet#ifdef CPU_SA1100
1532129198Scognet	if (cputype == CPU_ID_SA1100) {
1533129198Scognet		cpufuncs = sa11x0_cpufuncs;
1534129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* SA needs it	*/
1535129198Scognet		get_cachetype_table();
1536129198Scognet		pmap_pte_init_sa1();
1537129198Scognet		/* Use powersave on this CPU. */
1538129198Scognet		cpu_do_powersave = 1;
1539129198Scognet
1540166655Scognet		goto out;
1541129198Scognet	}
1542129198Scognet#endif	/* CPU_SA1100 */
1543129198Scognet#ifdef CPU_SA1110
1544129198Scognet	if (cputype == CPU_ID_SA1110) {
1545129198Scognet		cpufuncs = sa11x0_cpufuncs;
1546129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* SA needs it	*/
1547129198Scognet		get_cachetype_table();
1548129198Scognet		pmap_pte_init_sa1();
1549129198Scognet		/* Use powersave on this CPU. */
1550129198Scognet		cpu_do_powersave = 1;
1551129198Scognet
1552166655Scognet		goto out;
1553129198Scognet	}
1554129198Scognet#endif	/* CPU_SA1110 */
1555207611Skevlo#if defined(CPU_FA526) || defined(CPU_FA626TE)
1556207611Skevlo	if (cputype == CPU_ID_FA526 || cputype == CPU_ID_FA626TE) {
1557201468Srpaulo		cpufuncs = fa526_cpufuncs;
1558201468Srpaulo		cpu_reset_needs_v4_MMU_disable = 1;	/* SA needs it	*/
1559201468Srpaulo		get_cachetype_cp15();
1560201468Srpaulo		pmap_pte_init_generic();
1561201468Srpaulo
1562201468Srpaulo		/* Use powersave on this CPU. */
1563201468Srpaulo		cpu_do_powersave = 1;
1564201468Srpaulo
1565201468Srpaulo		goto out;
1566201468Srpaulo	}
1567207611Skevlo#endif	/* CPU_FA526 || CPU_FA626TE */
1568129198Scognet#ifdef CPU_IXP12X0
1569129198Scognet        if (cputype == CPU_ID_IXP1200) {
1570129198Scognet                cpufuncs = ixp12x0_cpufuncs;
1571129198Scognet                cpu_reset_needs_v4_MMU_disable = 1;
1572129198Scognet                get_cachetype_table();
1573129198Scognet                pmap_pte_init_sa1();
1574166655Scognet		goto out;
1575129198Scognet        }
1576129198Scognet#endif  /* CPU_IXP12X0 */
1577129198Scognet#ifdef CPU_XSCALE_80200
1578129198Scognet	if (cputype == CPU_ID_80200) {
1579129198Scognet		int rev = cpufunc_id() & CPU_ID_REVISION_MASK;
1580129198Scognet
1581129198Scognet		i80200_icu_init();
1582129198Scognet
1583129198Scognet#if defined(XSCALE_CCLKCFG)
1584129198Scognet		/*
1585129198Scognet		 * Crank CCLKCFG to maximum legal value.
1586129198Scognet		 */
1587129198Scognet		__asm __volatile ("mcr p14, 0, %0, c6, c0, 0"
1588129198Scognet			:
1589129198Scognet			: "r" (XSCALE_CCLKCFG));
1590129198Scognet#endif
1591129198Scognet
1592129198Scognet		/*
1593129198Scognet		 * XXX Disable ECC in the Bus Controller Unit; we
1594129198Scognet		 * don't really support it, yet.  Clear any pending
1595129198Scognet		 * error indications.
1596129198Scognet		 */
1597129198Scognet		__asm __volatile("mcr p13, 0, %0, c0, c1, 0"
1598129198Scognet			:
1599129198Scognet			: "r" (BCUCTL_E0|BCUCTL_E1|BCUCTL_EV));
1600129198Scognet
1601129198Scognet		cpufuncs = xscale_cpufuncs;
1602129198Scognet		/*
1603129198Scognet		 * i80200 errata: Step-A0 and A1 have a bug where
1604129198Scognet		 * D$ dirty bits are not cleared on "invalidate by
1605129198Scognet		 * address".
1606129198Scognet		 *
1607129198Scognet		 * Workaround: Clean cache line before invalidating.
1608129198Scognet		 */
1609129198Scognet		if (rev == 0 || rev == 1)
1610129198Scognet			cpufuncs.cf_dcache_inv_range = xscale_cache_purgeD_rng;
1611129198Scognet
1612129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
1613129198Scognet		get_cachetype_cp15();
1614129198Scognet		pmap_pte_init_xscale();
1615166655Scognet		goto out;
1616129198Scognet	}
1617129198Scognet#endif /* CPU_XSCALE_80200 */
1618161592Scognet#if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219)
1619129198Scognet	if (cputype == CPU_ID_80321_400 || cputype == CPU_ID_80321_600 ||
1620161592Scognet	    cputype == CPU_ID_80321_400_B0 || cputype == CPU_ID_80321_600_B0 ||
1621161592Scognet	    cputype == CPU_ID_80219_400 || cputype == CPU_ID_80219_600) {
1622129198Scognet		cpufuncs = xscale_cpufuncs;
1623129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
1624129198Scognet		get_cachetype_cp15();
1625129198Scognet		pmap_pte_init_xscale();
1626166655Scognet		goto out;
1627129198Scognet	}
1628129198Scognet#endif /* CPU_XSCALE_80321 */
1629161592Scognet
1630164080Scognet#if defined(CPU_XSCALE_81342)
1631164080Scognet	if (cputype == CPU_ID_81342) {
1632164080Scognet		cpufuncs = xscalec3_cpufuncs;
1633164080Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
1634164080Scognet		get_cachetype_cp15();
1635164080Scognet		pmap_pte_init_xscale();
1636166655Scognet		goto out;
1637164080Scognet	}
1638164080Scognet#endif /* CPU_XSCALE_81342 */
1639129198Scognet#ifdef CPU_XSCALE_PXA2X0
1640129198Scognet	/* ignore core revision to test PXA2xx CPUs */
1641129198Scognet	if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA250 ||
1642191817Sstas	    (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X ||
1643129198Scognet	    (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA210) {
1644129198Scognet
1645129198Scognet		cpufuncs = xscale_cpufuncs;
1646129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
1647129198Scognet		get_cachetype_cp15();
1648129198Scognet		pmap_pte_init_xscale();
1649129198Scognet
1650129198Scognet		/* Use powersave on this CPU. */
1651129198Scognet		cpu_do_powersave = 1;
1652129198Scognet
1653166655Scognet		goto out;
1654129198Scognet	}
1655129198Scognet#endif /* CPU_XSCALE_PXA2X0 */
1656129198Scognet#ifdef CPU_XSCALE_IXP425
1657129198Scognet	if (cputype == CPU_ID_IXP425_533 || cputype == CPU_ID_IXP425_400 ||
1658186352Ssam            cputype == CPU_ID_IXP425_266 || cputype == CPU_ID_IXP435) {
1659129198Scognet
1660129198Scognet		cpufuncs = xscale_cpufuncs;
1661129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
1662129198Scognet		get_cachetype_cp15();
1663129198Scognet		pmap_pte_init_xscale();
1664129198Scognet
1665166655Scognet		goto out;
1666129198Scognet	}
1667129198Scognet#endif /* CPU_XSCALE_IXP425 */
1668129198Scognet	/*
1669129198Scognet	 * Bzzzz. And the answer was ...
1670129198Scognet	 */
1671129198Scognet	panic("No support for this CPU type (%08x) in kernel", cputype);
1672129198Scognet	return(ARCHITECTURE_NOT_PRESENT);
1673166655Scognetout:
1674166655Scognet	uma_set_align(arm_dcache_align_mask);
1675166655Scognet	return (0);
1676129198Scognet}
1677129198Scognet
1678129198Scognet/*
1679129198Scognet * Fixup routines for data and prefetch aborts.
1680129198Scognet *
1681129198Scognet * Several compile time symbols are used
1682129198Scognet *
1683129198Scognet * DEBUG_FAULT_CORRECTION - Print debugging information during the
1684129198Scognet * correction of registers after a fault.
1685129198Scognet * ARM6_LATE_ABORT - ARM6 supports both early and late aborts
1686129198Scognet * when defined should use late aborts
1687129198Scognet */
1688129198Scognet
1689129198Scognet
1690129198Scognet/*
1691129198Scognet * Null abort fixup routine.
1692129198Scognet * For use when no fixup is required.
1693129198Scognet */
1694129198Scognetint
1695129198Scognetcpufunc_null_fixup(arg)
1696129198Scognet	void *arg;
1697129198Scognet{
1698129198Scognet	return(ABORT_FIXUP_OK);
1699129198Scognet}
1700129198Scognet
1701129198Scognet
1702146619Scognet#if defined(CPU_ARM7TDMI)
1703129198Scognet
1704129198Scognet#ifdef DEBUG_FAULT_CORRECTION
1705129198Scognet#define DFC_PRINTF(x)		printf x
1706129198Scognet#define DFC_DISASSEMBLE(x)	disassemble(x)
1707129198Scognet#else
1708129198Scognet#define DFC_PRINTF(x)		/* nothing */
1709129198Scognet#define DFC_DISASSEMBLE(x)	/* nothing */
1710129198Scognet#endif
1711129198Scognet
1712129198Scognet/*
1713129198Scognet * "Early" data abort fixup.
1714129198Scognet *
1715129198Scognet * For ARM2, ARM2as, ARM3 and ARM6 (in early-abort mode).  Also used
1716129198Scognet * indirectly by ARM6 (in late-abort mode) and ARM7[TDMI].
1717129198Scognet *
1718129198Scognet * In early aborts, we may have to fix up LDM, STM, LDC and STC.
1719129198Scognet */
1720129198Scognetint
1721129198Scognetearly_abort_fixup(arg)
1722129198Scognet	void *arg;
1723129198Scognet{
1724257217Sian	struct trapframe *frame = arg;
1725129198Scognet	u_int fault_pc;
1726129198Scognet	u_int fault_instruction;
1727129198Scognet	int saved_lr = 0;
1728129198Scognet
1729129198Scognet	if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
1730129198Scognet
1731129198Scognet		/* Ok an abort in SVC mode */
1732129198Scognet
1733129198Scognet		/*
1734129198Scognet		 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage
1735129198Scognet		 * as the fault happened in svc mode but we need it in the
1736129198Scognet		 * usr slot so we can treat the registers as an array of ints
1737129198Scognet		 * during fixing.
1738129198Scognet		 * NOTE: This PC is in the position but writeback is not
1739129198Scognet		 * allowed on r15.
1740129198Scognet		 * Doing it like this is more efficient than trapping this
1741129198Scognet		 * case in all possible locations in the following fixup code.
1742129198Scognet		 */
1743129198Scognet
1744129198Scognet		saved_lr = frame->tf_usr_lr;
1745129198Scognet		frame->tf_usr_lr = frame->tf_svc_lr;
1746129198Scognet
1747129198Scognet		/*
1748129198Scognet		 * Note the trapframe does not have the SVC r13 so a fault
1749129198Scognet		 * from an instruction with writeback to r13 in SVC mode is
1750129198Scognet		 * not allowed. This should not happen as the kstack is
1751129198Scognet		 * always valid.
1752129198Scognet		 */
1753129198Scognet	}
1754129198Scognet
1755129198Scognet	/* Get fault address and status from the CPU */
1756129198Scognet
1757129198Scognet	fault_pc = frame->tf_pc;
1758129198Scognet	fault_instruction = *((volatile unsigned int *)fault_pc);
1759129198Scognet
1760129198Scognet	/* Decode the fault instruction and fix the registers as needed */
1761129198Scognet
1762129198Scognet	if ((fault_instruction & 0x0e000000) == 0x08000000) {
1763129198Scognet		int base;
1764129198Scognet		int loop;
1765129198Scognet		int count;
1766129198Scognet		int *registers = &frame->tf_r0;
1767236991Simp
1768129198Scognet		DFC_PRINTF(("LDM/STM\n"));
1769129198Scognet		DFC_DISASSEMBLE(fault_pc);
1770129198Scognet		if (fault_instruction & (1 << 21)) {
1771129198Scognet			DFC_PRINTF(("This instruction must be corrected\n"));
1772129198Scognet			base = (fault_instruction >> 16) & 0x0f;
1773129198Scognet			if (base == 15)
1774129198Scognet				return ABORT_FIXUP_FAILED;
1775129198Scognet			/* Count registers transferred */
1776129198Scognet			count = 0;
1777129198Scognet			for (loop = 0; loop < 16; ++loop) {
1778129198Scognet				if (fault_instruction & (1<<loop))
1779129198Scognet					++count;
1780129198Scognet			}
1781129198Scognet			DFC_PRINTF(("%d registers used\n", count));
1782129198Scognet			DFC_PRINTF(("Corrected r%d by %d bytes ",
1783129198Scognet				       base, count * 4));
1784129198Scognet			if (fault_instruction & (1 << 23)) {
1785129198Scognet				DFC_PRINTF(("down\n"));
1786129198Scognet				registers[base] -= count * 4;
1787129198Scognet			} else {
1788129198Scognet				DFC_PRINTF(("up\n"));
1789129198Scognet				registers[base] += count * 4;
1790129198Scognet			}
1791129198Scognet		}
1792129198Scognet	} else if ((fault_instruction & 0x0e000000) == 0x0c000000) {
1793129198Scognet		int base;
1794129198Scognet		int offset;
1795129198Scognet		int *registers = &frame->tf_r0;
1796129198Scognet
1797129198Scognet		/* REGISTER CORRECTION IS REQUIRED FOR THESE INSTRUCTIONS */
1798129198Scognet
1799129198Scognet		DFC_DISASSEMBLE(fault_pc);
1800129198Scognet
1801129198Scognet		/* Only need to fix registers if write back is turned on */
1802129198Scognet
1803129198Scognet		if ((fault_instruction & (1 << 21)) != 0) {
1804129198Scognet			base = (fault_instruction >> 16) & 0x0f;
1805129198Scognet			if (base == 13 &&
1806129198Scognet			    (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE)
1807129198Scognet				return ABORT_FIXUP_FAILED;
1808129198Scognet			if (base == 15)
1809129198Scognet				return ABORT_FIXUP_FAILED;
1810129198Scognet
1811129198Scognet			offset = (fault_instruction & 0xff) << 2;
1812129198Scognet			DFC_PRINTF(("r%d=%08x\n", base, registers[base]));
1813129198Scognet			if ((fault_instruction & (1 << 23)) != 0)
1814129198Scognet				offset = -offset;
1815129198Scognet			registers[base] += offset;
1816129198Scognet			DFC_PRINTF(("r%d=%08x\n", base, registers[base]));
1817129198Scognet		}
1818129198Scognet	} else if ((fault_instruction & 0x0e000000) == 0x0c000000)
1819129198Scognet		return ABORT_FIXUP_FAILED;
1820129198Scognet
1821129198Scognet	if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
1822129198Scognet
1823129198Scognet		/* Ok an abort in SVC mode */
1824129198Scognet
1825129198Scognet		/*
1826129198Scognet		 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage
1827129198Scognet		 * as the fault happened in svc mode but we need it in the
1828129198Scognet		 * usr slot so we can treat the registers as an array of ints
1829129198Scognet		 * during fixing.
1830129198Scognet		 * NOTE: This PC is in the position but writeback is not
1831129198Scognet		 * allowed on r15.
1832129198Scognet		 * Doing it like this is more efficient than trapping this
1833129198Scognet		 * case in all possible locations in the prior fixup code.
1834129198Scognet		 */
1835129198Scognet
1836129198Scognet		frame->tf_svc_lr = frame->tf_usr_lr;
1837129198Scognet		frame->tf_usr_lr = saved_lr;
1838129198Scognet
1839129198Scognet		/*
1840129198Scognet		 * Note the trapframe does not have the SVC r13 so a fault
1841129198Scognet		 * from an instruction with writeback to r13 in SVC mode is
1842129198Scognet		 * not allowed. This should not happen as the kstack is
1843129198Scognet		 * always valid.
1844129198Scognet		 */
1845129198Scognet	}
1846129198Scognet
1847129198Scognet	return(ABORT_FIXUP_OK);
1848129198Scognet}
1849129198Scognet#endif	/* CPU_ARM2/250/3/6/7 */
1850129198Scognet
1851129198Scognet
1852146619Scognet#if defined(CPU_ARM7TDMI)
1853129198Scognet/*
1854129198Scognet * "Late" (base updated) data abort fixup
1855129198Scognet *
1856129198Scognet * For ARM6 (in late-abort mode) and ARM7.
1857129198Scognet *
1858129198Scognet * In this model, all data-transfer instructions need fixing up.  We defer
1859129198Scognet * LDM, STM, LDC and STC fixup to the early-abort handler.
1860129198Scognet */
1861129198Scognetint
1862129198Scognetlate_abort_fixup(arg)
1863129198Scognet	void *arg;
1864129198Scognet{
1865257217Sian	struct trapframe *frame = arg;
1866129198Scognet	u_int fault_pc;
1867129198Scognet	u_int fault_instruction;
1868129198Scognet	int saved_lr = 0;
1869129198Scognet
1870129198Scognet	if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
1871129198Scognet
1872129198Scognet		/* Ok an abort in SVC mode */
1873129198Scognet
1874129198Scognet		/*
1875129198Scognet		 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage
1876129198Scognet		 * as the fault happened in svc mode but we need it in the
1877129198Scognet		 * usr slot so we can treat the registers as an array of ints
1878129198Scognet		 * during fixing.
1879129198Scognet		 * NOTE: This PC is in the position but writeback is not
1880129198Scognet		 * allowed on r15.
1881129198Scognet		 * Doing it like this is more efficient than trapping this
1882129198Scognet		 * case in all possible locations in the following fixup code.
1883129198Scognet		 */
1884129198Scognet
1885129198Scognet		saved_lr = frame->tf_usr_lr;
1886129198Scognet		frame->tf_usr_lr = frame->tf_svc_lr;
1887129198Scognet
1888129198Scognet		/*
1889129198Scognet		 * Note the trapframe does not have the SVC r13 so a fault
1890129198Scognet		 * from an instruction with writeback to r13 in SVC mode is
1891129198Scognet		 * not allowed. This should not happen as the kstack is
1892129198Scognet		 * always valid.
1893129198Scognet		 */
1894129198Scognet	}
1895129198Scognet
1896129198Scognet	/* Get fault address and status from the CPU */
1897129198Scognet
1898129198Scognet	fault_pc = frame->tf_pc;
1899129198Scognet	fault_instruction = *((volatile unsigned int *)fault_pc);
1900129198Scognet
1901129198Scognet	/* Decode the fault instruction and fix the registers as needed */
1902129198Scognet
1903129198Scognet	/* Was is a swap instruction ? */
1904129198Scognet
1905129198Scognet	if ((fault_instruction & 0x0fb00ff0) == 0x01000090) {
1906129198Scognet		DFC_DISASSEMBLE(fault_pc);
1907129198Scognet	} else if ((fault_instruction & 0x0c000000) == 0x04000000) {
1908129198Scognet
1909129198Scognet		/* Was is a ldr/str instruction */
1910129198Scognet		/* This is for late abort only */
1911129198Scognet
1912129198Scognet		int base;
1913129198Scognet		int offset;
1914129198Scognet		int *registers = &frame->tf_r0;
1915129198Scognet
1916129198Scognet		DFC_DISASSEMBLE(fault_pc);
1917129198Scognet
1918129198Scognet		/* This is for late abort only */
1919129198Scognet
1920129198Scognet		if ((fault_instruction & (1 << 24)) == 0
1921129198Scognet		    || (fault_instruction & (1 << 21)) != 0) {
1922129198Scognet			/* postindexed ldr/str with no writeback */
1923129198Scognet
1924129198Scognet			base = (fault_instruction >> 16) & 0x0f;
1925129198Scognet			if (base == 13 &&
1926129198Scognet			    (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE)
1927129198Scognet				return ABORT_FIXUP_FAILED;
1928129198Scognet			if (base == 15)
1929129198Scognet				return ABORT_FIXUP_FAILED;
1930129198Scognet			DFC_PRINTF(("late abt fix: r%d=%08x : ",
1931129198Scognet				       base, registers[base]));
1932129198Scognet			if ((fault_instruction & (1 << 25)) == 0) {
1933129198Scognet				/* Immediate offset - easy */
1934129198Scognet
1935129198Scognet				offset = fault_instruction & 0xfff;
1936129198Scognet				if ((fault_instruction & (1 << 23)))
1937129198Scognet					offset = -offset;
1938129198Scognet				registers[base] += offset;
1939129198Scognet				DFC_PRINTF(("imm=%08x ", offset));
1940129198Scognet			} else {
1941129198Scognet				/* offset is a shifted register */
1942129198Scognet				int shift;
1943129198Scognet
1944129198Scognet				offset = fault_instruction & 0x0f;
1945129198Scognet				if (offset == base)
1946129198Scognet					return ABORT_FIXUP_FAILED;
1947236991Simp
1948129198Scognet				/*
1949129198Scognet				 * Register offset - hard we have to
1950129198Scognet				 * cope with shifts !
1951129198Scognet				 */
1952129198Scognet				offset = registers[offset];
1953129198Scognet
1954129198Scognet				if ((fault_instruction & (1 << 4)) == 0)
1955129198Scognet					/* shift with amount */
1956129198Scognet					shift = (fault_instruction >> 7) & 0x1f;
1957129198Scognet				else {
1958129198Scognet					/* shift with register */
1959129198Scognet					if ((fault_instruction & (1 << 7)) != 0)
1960129198Scognet						/* undefined for now so bail out */
1961129198Scognet						return ABORT_FIXUP_FAILED;
1962129198Scognet					shift = ((fault_instruction >> 8) & 0xf);
1963129198Scognet					if (base == shift)
1964129198Scognet						return ABORT_FIXUP_FAILED;
1965129198Scognet					DFC_PRINTF(("shift reg=%d ", shift));
1966129198Scognet					shift = registers[shift];
1967129198Scognet				}
1968129198Scognet				DFC_PRINTF(("shift=%08x ", shift));
1969129198Scognet				switch (((fault_instruction >> 5) & 0x3)) {
1970129198Scognet				case 0 : /* Logical left */
1971129198Scognet					offset = (int)(((u_int)offset) << shift);
1972129198Scognet					break;
1973129198Scognet				case 1 : /* Logical Right */
1974129198Scognet					if (shift == 0) shift = 32;
1975129198Scognet					offset = (int)(((u_int)offset) >> shift);
1976129198Scognet					break;
1977129198Scognet				case 2 : /* Arithmetic Right */
1978129198Scognet					if (shift == 0) shift = 32;
1979129198Scognet					offset = (int)(((int)offset) >> shift);
1980129198Scognet					break;
1981129198Scognet				case 3 : /* Rotate right (rol or rxx) */
1982129198Scognet					return ABORT_FIXUP_FAILED;
1983129198Scognet					break;
1984129198Scognet				}
1985129198Scognet
1986129198Scognet				DFC_PRINTF(("abt: fixed LDR/STR with "
1987129198Scognet					       "register offset\n"));
1988129198Scognet				if ((fault_instruction & (1 << 23)))
1989129198Scognet					offset = -offset;
1990129198Scognet				DFC_PRINTF(("offset=%08x ", offset));
1991129198Scognet				registers[base] += offset;
1992129198Scognet			}
1993129198Scognet			DFC_PRINTF(("r%d=%08x\n", base, registers[base]));
1994129198Scognet		}
1995129198Scognet	}
1996129198Scognet
1997129198Scognet	if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
1998129198Scognet
1999129198Scognet		/* Ok an abort in SVC mode */
2000129198Scognet
2001129198Scognet		/*
2002129198Scognet		 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage
2003129198Scognet		 * as the fault happened in svc mode but we need it in the
2004129198Scognet		 * usr slot so we can treat the registers as an array of ints
2005129198Scognet		 * during fixing.
2006129198Scognet		 * NOTE: This PC is in the position but writeback is not
2007129198Scognet		 * allowed on r15.
2008129198Scognet		 * Doing it like this is more efficient than trapping this
2009129198Scognet		 * case in all possible locations in the prior fixup code.
2010129198Scognet		 */
2011129198Scognet
2012129198Scognet		frame->tf_svc_lr = frame->tf_usr_lr;
2013129198Scognet		frame->tf_usr_lr = saved_lr;
2014129198Scognet
2015129198Scognet		/*
2016129198Scognet		 * Note the trapframe does not have the SVC r13 so a fault
2017129198Scognet		 * from an instruction with writeback to r13 in SVC mode is
2018129198Scognet		 * not allowed. This should not happen as the kstack is
2019129198Scognet		 * always valid.
2020129198Scognet		 */
2021129198Scognet	}
2022129198Scognet
2023129198Scognet	/*
2024129198Scognet	 * Now let the early-abort fixup routine have a go, in case it
2025129198Scognet	 * was an LDM, STM, LDC or STC that faulted.
2026129198Scognet	 */
2027129198Scognet
2028129198Scognet	return early_abort_fixup(arg);
2029129198Scognet}
2030146619Scognet#endif	/* CPU_ARM7TDMI */
2031129198Scognet
2032129198Scognet/*
2033129198Scognet * CPU Setup code
2034129198Scognet */
2035129198Scognet
2036146619Scognet#if defined(CPU_ARM7TDMI) || defined(CPU_ARM8) || defined (CPU_ARM9) || \
2037172738Simp  defined(CPU_ARM9E) || \
2038161592Scognet  defined(CPU_SA110) || defined(CPU_SA1100) || defined(CPU_SA1110) ||	\
2039161592Scognet  defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) ||		\
2040161592Scognet  defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) ||		\
2041172738Simp  defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \
2042244480Sgonzo  defined(CPU_ARM10) ||  defined(CPU_ARM1136) || defined(CPU_ARM1176) ||\
2043207611Skevlo  defined(CPU_FA526) || defined(CPU_FA626TE)
2044129198Scognet
2045129198Scognet#define IGN	0
2046129198Scognet#define OR	1
2047129198Scognet#define BIC	2
2048129198Scognet
2049129198Scognetstruct cpu_option {
2050129198Scognet	char	*co_name;
2051129198Scognet	int	co_falseop;
2052129198Scognet	int	co_trueop;
2053129198Scognet	int	co_value;
2054129198Scognet};
2055129198Scognet
2056137498Strhodesstatic u_int parse_cpu_options(char *, struct cpu_option *, u_int);
2057129198Scognet
2058129198Scognetstatic u_int
2059129198Scognetparse_cpu_options(args, optlist, cpuctrl)
2060129198Scognet	char *args;
2061236991Simp	struct cpu_option *optlist;
2062236991Simp	u_int cpuctrl;
2063129198Scognet{
2064129198Scognet	int integer;
2065129198Scognet
2066129198Scognet	if (args == NULL)
2067129198Scognet		return(cpuctrl);
2068129198Scognet
2069129198Scognet	while (optlist->co_name) {
2070129198Scognet		if (get_bootconf_option(args, optlist->co_name,
2071129198Scognet		    BOOTOPT_TYPE_BOOLEAN, &integer)) {
2072129198Scognet			if (integer) {
2073129198Scognet				if (optlist->co_trueop == OR)
2074129198Scognet					cpuctrl |= optlist->co_value;
2075129198Scognet				else if (optlist->co_trueop == BIC)
2076129198Scognet					cpuctrl &= ~optlist->co_value;
2077129198Scognet			} else {
2078129198Scognet				if (optlist->co_falseop == OR)
2079129198Scognet					cpuctrl |= optlist->co_value;
2080129198Scognet				else if (optlist->co_falseop == BIC)
2081129198Scognet					cpuctrl &= ~optlist->co_value;
2082129198Scognet			}
2083129198Scognet		}
2084129198Scognet		++optlist;
2085129198Scognet	}
2086129198Scognet	return(cpuctrl);
2087129198Scognet}
2088161592Scognet#endif /* CPU_ARM7TDMI || CPU_ARM8 || CPU_SA110 || XSCALE*/
2089129198Scognet
2090146619Scognet#if defined(CPU_ARM7TDMI) || defined(CPU_ARM8)
2091129198Scognetstruct cpu_option arm678_options[] = {
2092129198Scognet#ifdef COMPAT_12
2093129198Scognet	{ "nocache",		IGN, BIC, CPU_CONTROL_IDC_ENABLE },
2094129198Scognet	{ "nowritebuf",		IGN, BIC, CPU_CONTROL_WBUF_ENABLE },
2095129198Scognet#endif	/* COMPAT_12 */
2096129198Scognet	{ "cpu.cache",		BIC, OR,  CPU_CONTROL_IDC_ENABLE },
2097129198Scognet	{ "cpu.nocache",	OR,  BIC, CPU_CONTROL_IDC_ENABLE },
2098129198Scognet	{ "cpu.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2099129198Scognet	{ "cpu.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
2100129198Scognet	{ NULL,			IGN, IGN, 0 }
2101129198Scognet};
2102129198Scognet
2103129198Scognet#endif	/* CPU_ARM6 || CPU_ARM7 || CPU_ARM7TDMI || CPU_ARM8 */
2104129198Scognet
2105129198Scognet#ifdef CPU_ARM7TDMI
2106129198Scognetstruct cpu_option arm7tdmi_options[] = {
2107129198Scognet	{ "arm7.cache",		BIC, OR,  CPU_CONTROL_IDC_ENABLE },
2108129198Scognet	{ "arm7.nocache",	OR,  BIC, CPU_CONTROL_IDC_ENABLE },
2109129198Scognet	{ "arm7.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2110129198Scognet	{ "arm7.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
2111129198Scognet#ifdef COMPAT_12
2112129198Scognet	{ "fpaclk2",		BIC, OR,  CPU_CONTROL_CPCLK },
2113129198Scognet#endif	/* COMPAT_12 */
2114129198Scognet	{ "arm700.fpaclk",	BIC, OR,  CPU_CONTROL_CPCLK },
2115129198Scognet	{ NULL,			IGN, IGN, 0 }
2116129198Scognet};
2117129198Scognet
2118129198Scognetvoid
2119129198Scognetarm7tdmi_setup(args)
2120129198Scognet	char *args;
2121129198Scognet{
2122129198Scognet	int cpuctrl;
2123129198Scognet
2124129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2125129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2126129198Scognet		 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE;
2127129198Scognet
2128129198Scognet	cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl);
2129129198Scognet	cpuctrl = parse_cpu_options(args, arm7tdmi_options, cpuctrl);
2130129198Scognet
2131129198Scognet#ifdef __ARMEB__
2132129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2133129198Scognet#endif
2134129198Scognet
2135129198Scognet	/* Clear out the cache */
2136129198Scognet	cpu_idcache_wbinv_all();
2137129198Scognet
2138129198Scognet	/* Set the control register */
2139129198Scognet	ctrl = cpuctrl;
2140129198Scognet	cpu_control(0xffffffff, cpuctrl);
2141129198Scognet}
2142129198Scognet#endif	/* CPU_ARM7TDMI */
2143129198Scognet
2144129198Scognet#ifdef CPU_ARM8
2145129198Scognetstruct cpu_option arm8_options[] = {
2146129198Scognet	{ "arm8.cache",		BIC, OR,  CPU_CONTROL_IDC_ENABLE },
2147129198Scognet	{ "arm8.nocache",	OR,  BIC, CPU_CONTROL_IDC_ENABLE },
2148129198Scognet	{ "arm8.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2149129198Scognet	{ "arm8.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
2150129198Scognet#ifdef COMPAT_12
2151129198Scognet	{ "branchpredict", 	BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
2152129198Scognet#endif	/* COMPAT_12 */
2153129198Scognet	{ "cpu.branchpredict", 	BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
2154129198Scognet	{ "arm8.branchpredict",	BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
2155129198Scognet	{ NULL,			IGN, IGN, 0 }
2156129198Scognet};
2157129198Scognet
2158129198Scognetvoid
2159129198Scognetarm8_setup(args)
2160129198Scognet	char *args;
2161129198Scognet{
2162129198Scognet	int integer;
2163129198Scognet	int cpuctrl, cpuctrlmask;
2164129198Scognet	int clocktest;
2165129198Scognet	int setclock = 0;
2166129198Scognet
2167129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2168129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2169129198Scognet		 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE;
2170129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2171129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2172129198Scognet		 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE
2173129198Scognet		 | CPU_CONTROL_BPRD_ENABLE | CPU_CONTROL_ROM_ENABLE
2174129198Scognet		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE;
2175129198Scognet
2176129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2177129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2178129198Scognet#endif
2179129198Scognet
2180129198Scognet	cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl);
2181129198Scognet	cpuctrl = parse_cpu_options(args, arm8_options, cpuctrl);
2182129198Scognet
2183129198Scognet#ifdef __ARMEB__
2184129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2185129198Scognet#endif
2186129198Scognet
2187129198Scognet	/* Get clock configuration */
2188129198Scognet	clocktest = arm8_clock_config(0, 0) & 0x0f;
2189129198Scognet
2190129198Scognet	/* Special ARM8 clock and test configuration */
2191129198Scognet	if (get_bootconf_option(args, "arm8.clock.reset", BOOTOPT_TYPE_BOOLEAN, &integer)) {
2192129198Scognet		clocktest = 0;
2193129198Scognet		setclock = 1;
2194129198Scognet	}
2195129198Scognet	if (get_bootconf_option(args, "arm8.clock.dynamic", BOOTOPT_TYPE_BOOLEAN, &integer)) {
2196129198Scognet		if (integer)
2197129198Scognet			clocktest |= 0x01;
2198129198Scognet		else
2199129198Scognet			clocktest &= ~(0x01);
2200129198Scognet		setclock = 1;
2201129198Scognet	}
2202129198Scognet	if (get_bootconf_option(args, "arm8.clock.sync", BOOTOPT_TYPE_BOOLEAN, &integer)) {
2203129198Scognet		if (integer)
2204129198Scognet			clocktest |= 0x02;
2205129198Scognet		else
2206129198Scognet			clocktest &= ~(0x02);
2207129198Scognet		setclock = 1;
2208129198Scognet	}
2209129198Scognet	if (get_bootconf_option(args, "arm8.clock.fast", BOOTOPT_TYPE_BININT, &integer)) {
2210129198Scognet		clocktest = (clocktest & ~0xc0) | (integer & 3) << 2;
2211129198Scognet		setclock = 1;
2212129198Scognet	}
2213129198Scognet	if (get_bootconf_option(args, "arm8.test", BOOTOPT_TYPE_BININT, &integer)) {
2214129198Scognet		clocktest |= (integer & 7) << 5;
2215129198Scognet		setclock = 1;
2216129198Scognet	}
2217129198Scognet
2218129198Scognet	/* Clear out the cache */
2219129198Scognet	cpu_idcache_wbinv_all();
2220129198Scognet
2221129198Scognet	/* Set the control register */
2222129198Scognet	ctrl = cpuctrl;
2223129198Scognet	cpu_control(0xffffffff, cpuctrl);
2224129198Scognet
2225236991Simp	/* Set the clock/test register */
2226129198Scognet	if (setclock)
2227129198Scognet		arm8_clock_config(0x7f, clocktest);
2228129198Scognet}
2229129198Scognet#endif	/* CPU_ARM8 */
2230129198Scognet
2231129198Scognet#ifdef CPU_ARM9
2232129198Scognetstruct cpu_option arm9_options[] = {
2233129198Scognet	{ "cpu.cache",		BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2234129198Scognet	{ "cpu.nocache",	OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2235129198Scognet	{ "arm9.cache",	BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2236129198Scognet	{ "arm9.icache",	BIC, OR,  CPU_CONTROL_IC_ENABLE },
2237129198Scognet	{ "arm9.dcache",	BIC, OR,  CPU_CONTROL_DC_ENABLE },
2238129198Scognet	{ "cpu.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2239129198Scognet	{ "cpu.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
2240129198Scognet	{ "arm9.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2241129198Scognet	{ NULL,			IGN, IGN, 0 }
2242129198Scognet};
2243129198Scognet
2244129198Scognetvoid
2245129198Scognetarm9_setup(args)
2246129198Scognet	char *args;
2247129198Scognet{
2248129198Scognet	int cpuctrl, cpuctrlmask;
2249129198Scognet
2250129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2251129198Scognet	    | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2252129198Scognet	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2253157618Scognet	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE |
2254157618Scognet	    CPU_CONTROL_ROUNDROBIN;
2255129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2256129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2257129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2258129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
2259129198Scognet		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
2260146605Scognet		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_VECRELOC
2261146605Scognet		 | CPU_CONTROL_ROUNDROBIN;
2262129198Scognet
2263129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2264129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2265129198Scognet#endif
2266129198Scognet
2267129198Scognet	cpuctrl = parse_cpu_options(args, arm9_options, cpuctrl);
2268129198Scognet
2269129198Scognet#ifdef __ARMEB__
2270129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2271129198Scognet#endif
2272142050Scognet	if (vector_page == ARM_VECTORS_HIGH)
2273142050Scognet		cpuctrl |= CPU_CONTROL_VECRELOC;
2274129198Scognet
2275129198Scognet	/* Clear out the cache */
2276129198Scognet	cpu_idcache_wbinv_all();
2277129198Scognet
2278129198Scognet	/* Set the control register */
2279146605Scognet	cpu_control(cpuctrlmask, cpuctrl);
2280129198Scognet	ctrl = cpuctrl;
2281129198Scognet
2282129198Scognet}
2283129198Scognet#endif	/* CPU_ARM9 */
2284129198Scognet
2285172738Simp#if defined(CPU_ARM9E) || defined(CPU_ARM10)
2286129198Scognetstruct cpu_option arm10_options[] = {
2287129198Scognet	{ "cpu.cache",		BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2288129198Scognet	{ "cpu.nocache",	OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2289129198Scognet	{ "arm10.cache",	BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2290129198Scognet	{ "arm10.icache",	BIC, OR,  CPU_CONTROL_IC_ENABLE },
2291129198Scognet	{ "arm10.dcache",	BIC, OR,  CPU_CONTROL_DC_ENABLE },
2292129198Scognet	{ "cpu.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2293129198Scognet	{ "cpu.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
2294129198Scognet	{ "arm10.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2295129198Scognet	{ NULL,			IGN, IGN, 0 }
2296129198Scognet};
2297129198Scognet
2298129198Scognetvoid
2299129198Scognetarm10_setup(args)
2300129198Scognet	char *args;
2301129198Scognet{
2302129198Scognet	int cpuctrl, cpuctrlmask;
2303129198Scognet
2304129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
2305236991Simp	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2306129198Scognet	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE;
2307129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
2308129198Scognet	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2309129198Scognet	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
2310129198Scognet	    | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
2311129198Scognet	    | CPU_CONTROL_BPRD_ENABLE
2312129198Scognet	    | CPU_CONTROL_ROUNDROBIN | CPU_CONTROL_CPCLK;
2313129198Scognet
2314129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2315129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2316129198Scognet#endif
2317129198Scognet
2318129198Scognet	cpuctrl = parse_cpu_options(args, arm10_options, cpuctrl);
2319129198Scognet
2320129198Scognet#ifdef __ARMEB__
2321129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2322129198Scognet#endif
2323129198Scognet
2324129198Scognet	/* Clear out the cache */
2325129198Scognet	cpu_idcache_wbinv_all();
2326129198Scognet
2327129198Scognet	/* Now really make sure they are clean.  */
2328172738Simp	__asm __volatile ("mcr\tp15, 0, r0, c7, c7, 0" : : );
2329129198Scognet
2330174058Scognet	if (vector_page == ARM_VECTORS_HIGH)
2331174058Scognet		cpuctrl |= CPU_CONTROL_VECRELOC;
2332174058Scognet
2333129198Scognet	/* Set the control register */
2334129198Scognet	ctrl = cpuctrl;
2335129198Scognet	cpu_control(0xffffffff, cpuctrl);
2336129198Scognet
2337129198Scognet	/* And again. */
2338129198Scognet	cpu_idcache_wbinv_all();
2339129198Scognet}
2340172738Simp#endif	/* CPU_ARM9E || CPU_ARM10 */
2341129198Scognet
2342244480Sgonzo#if defined(CPU_ARM1136) || defined(CPU_ARM1176)
2343172738Simpstruct cpu_option arm11_options[] = {
2344172738Simp	{ "cpu.cache",		BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2345172738Simp	{ "cpu.nocache",	OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2346172738Simp	{ "arm11.cache",	BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2347172738Simp	{ "arm11.icache",	BIC, OR,  CPU_CONTROL_IC_ENABLE },
2348172738Simp	{ "arm11.dcache",	BIC, OR,  CPU_CONTROL_DC_ENABLE },
2349172738Simp	{ NULL,			IGN, IGN, 0 }
2350172738Simp};
2351172738Simp
2352172738Simpvoid
2353244480Sgonzoarm11x6_setup(char *args)
2354172738Simp{
2355244480Sgonzo	int cpuctrl, cpuctrl_wax;
2356244480Sgonzo	uint32_t auxctrl, auxctrl_wax;
2357244480Sgonzo	uint32_t tmp, tmp2;
2358244480Sgonzo	uint32_t sbz=0;
2359244480Sgonzo	uint32_t cpuid;
2360172738Simp
2361244480Sgonzo	cpuid = cpufunc_id();
2362244480Sgonzo
2363244480Sgonzo	cpuctrl =
2364244480Sgonzo		CPU_CONTROL_MMU_ENABLE  |
2365244480Sgonzo		CPU_CONTROL_DC_ENABLE   |
2366244480Sgonzo		CPU_CONTROL_WBUF_ENABLE |
2367244480Sgonzo		CPU_CONTROL_32BP_ENABLE |
2368244480Sgonzo		CPU_CONTROL_32BD_ENABLE |
2369244480Sgonzo		CPU_CONTROL_LABT_ENABLE |
2370244480Sgonzo		CPU_CONTROL_SYST_ENABLE |
2371244480Sgonzo		CPU_CONTROL_IC_ENABLE;
2372244480Sgonzo
2373244480Sgonzo	/*
2374244480Sgonzo	 * "write as existing" bits
2375244480Sgonzo	 * inverse of this is mask
2376244480Sgonzo	 */
2377244480Sgonzo	cpuctrl_wax =
2378244480Sgonzo		(3 << 30) | /* SBZ */
2379244480Sgonzo		(1 << 29) | /* FA */
2380244480Sgonzo		(1 << 28) | /* TR */
2381244480Sgonzo		(3 << 26) | /* SBZ */
2382244480Sgonzo		(3 << 19) | /* SBZ */
2383244480Sgonzo		(1 << 17);  /* SBZ */
2384244480Sgonzo
2385244480Sgonzo	cpuctrl |= CPU_CONTROL_BPRD_ENABLE;
2386244480Sgonzo	cpuctrl |= CPU_CONTROL_V6_EXTPAGE;
2387244480Sgonzo
2388172738Simp	cpuctrl = parse_cpu_options(args, arm11_options, cpuctrl);
2389244480Sgonzo
2390172738Simp#ifdef __ARMEB__
2391172738Simp	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2392172738Simp#endif
2393244480Sgonzo
2394239701Sgonzo	if (vector_page == ARM_VECTORS_HIGH)
2395239701Sgonzo		cpuctrl |= CPU_CONTROL_VECRELOC;
2396172738Simp
2397244480Sgonzo	auxctrl = 0;
2398244480Sgonzo	auxctrl_wax = ~0;
2399244480Sgonzo	/*
2400244480Sgonzo	 * This options enables the workaround for the 364296 ARM1136
2401244480Sgonzo	 * r0pX errata (possible cache data corruption with
2402244480Sgonzo	 * hit-under-miss enabled). It sets the undocumented bit 31 in
2403244480Sgonzo	 * the auxiliary control register and the FI bit in the control
2404244480Sgonzo	 * register, thus disabling hit-under-miss without putting the
2405244480Sgonzo	 * processor into full low interrupt latency mode. ARM11MPCore
2406244480Sgonzo	 * is not affected.
2407244480Sgonzo	 */
2408244480Sgonzo	if ((cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM1136JS) { /* ARM1136JSr0pX */
2409244480Sgonzo		cpuctrl |= CPU_CONTROL_FI_ENABLE;
2410244480Sgonzo		auxctrl = ARM1136_AUXCTL_PFI;
2411244480Sgonzo		auxctrl_wax = ~ARM1136_AUXCTL_PFI;
2412244480Sgonzo	}
2413244480Sgonzo
2414244480Sgonzo	/*
2415244480Sgonzo	 * Enable an errata workaround
2416244480Sgonzo	 */
2417244480Sgonzo	if ((cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM1176JZS) { /* ARM1176JZSr0 */
2418244480Sgonzo		auxctrl = ARM1176_AUXCTL_PHD;
2419244480Sgonzo		auxctrl_wax = ~ARM1176_AUXCTL_PHD;
2420244480Sgonzo	}
2421244480Sgonzo
2422244480Sgonzo	/* Clear out the cache */
2423172738Simp	cpu_idcache_wbinv_all();
2424172738Simp
2425244480Sgonzo	/* Now really make sure they are clean.  */
2426244480Sgonzo	__asm volatile ("mcr\tp15, 0, %0, c7, c7, 0" : : "r"(sbz));
2427244480Sgonzo
2428244480Sgonzo	/* Allow detection code to find the VFP if it's fitted.  */
2429244480Sgonzo	__asm volatile ("mcr\tp15, 0, %0, c1, c0, 2" : : "r" (0x0fffffff));
2430244480Sgonzo
2431172738Simp	/* Set the control register */
2432239701Sgonzo	ctrl = cpuctrl;
2433244480Sgonzo	cpu_control(~cpuctrl_wax, cpuctrl);
2434172738Simp
2435244480Sgonzo	__asm volatile ("mrc	p15, 0, %0, c1, c0, 1\n\t"
2436244480Sgonzo			"and	%1, %0, %2\n\t"
2437244480Sgonzo			"orr	%1, %1, %3\n\t"
2438244480Sgonzo			"teq	%0, %1\n\t"
2439244480Sgonzo			"mcrne	p15, 0, %1, c1, c0, 1\n\t"
2440244480Sgonzo			: "=r"(tmp), "=r"(tmp2) :
2441244480Sgonzo			  "r"(auxctrl_wax), "r"(auxctrl));
2442244480Sgonzo
2443244480Sgonzo	/* And again. */
2444172738Simp	cpu_idcache_wbinv_all();
2445172738Simp}
2446244480Sgonzo#endif  /* CPU_ARM1136 || CPU_ARM1176 */
2447172738Simp
2448239268Sgonzo#ifdef CPU_MV_PJ4B
2449239268Sgonzovoid
2450239268Sgonzopj4bv6_setup(char *args)
2451239268Sgonzo{
2452239268Sgonzo	int cpuctrl;
2453239268Sgonzo
2454239268Sgonzo	pj4b_config();
2455239268Sgonzo
2456239268Sgonzo	cpuctrl = CPU_CONTROL_MMU_ENABLE;
2457239268Sgonzo#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2458239268Sgonzo	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2459239268Sgonzo#endif
2460239268Sgonzo	cpuctrl |= CPU_CONTROL_DC_ENABLE;
2461239268Sgonzo	cpuctrl |= (0xf << 3);
2462239268Sgonzo#ifdef __ARMEB__
2463239268Sgonzo	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2464239268Sgonzo#endif
2465239268Sgonzo	cpuctrl |= CPU_CONTROL_SYST_ENABLE;
2466239268Sgonzo	cpuctrl |= CPU_CONTROL_BPRD_ENABLE;
2467239268Sgonzo	cpuctrl |= CPU_CONTROL_IC_ENABLE;
2468239268Sgonzo	if (vector_page == ARM_VECTORS_HIGH)
2469239268Sgonzo		cpuctrl |= CPU_CONTROL_VECRELOC;
2470239268Sgonzo	cpuctrl |= (0x5 << 16);
2471239268Sgonzo	cpuctrl |= CPU_CONTROL_V6_EXTPAGE;
2472239268Sgonzo	/* XXX not yet */
2473239268Sgonzo	/* cpuctrl |= CPU_CONTROL_L2_ENABLE; */
2474239268Sgonzo
2475239268Sgonzo	/* Make sure caches are clean.  */
2476239268Sgonzo	cpu_idcache_wbinv_all();
2477239268Sgonzo	cpu_l2cache_wbinv_all();
2478239268Sgonzo
2479239268Sgonzo	/* Set the control register */
2480239268Sgonzo	ctrl = cpuctrl;
2481239268Sgonzo	cpu_control(0xffffffff, cpuctrl);
2482239268Sgonzo
2483239268Sgonzo	cpu_idcache_wbinv_all();
2484239268Sgonzo	cpu_l2cache_wbinv_all();
2485239268Sgonzo}
2486239268Sgonzo
2487239268Sgonzovoid
2488239268Sgonzopj4bv7_setup(args)
2489239268Sgonzo	char *args;
2490239268Sgonzo{
2491239268Sgonzo	int cpuctrl;
2492239268Sgonzo
2493239268Sgonzo	pj4b_config();
2494239268Sgonzo
2495239268Sgonzo	cpuctrl = CPU_CONTROL_MMU_ENABLE;
2496239268Sgonzo#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2497239268Sgonzo	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2498239268Sgonzo#endif
2499239268Sgonzo	cpuctrl |= CPU_CONTROL_DC_ENABLE;
2500239268Sgonzo	cpuctrl |= (0xf << 3);
2501239268Sgonzo	cpuctrl |= CPU_CONTROL_BPRD_ENABLE;
2502239268Sgonzo	cpuctrl |= CPU_CONTROL_IC_ENABLE;
2503239268Sgonzo	if (vector_page == ARM_VECTORS_HIGH)
2504239268Sgonzo		cpuctrl |= CPU_CONTROL_VECRELOC;
2505239268Sgonzo	cpuctrl |= (0x5 << 16) | (1 < 22);
2506239268Sgonzo	cpuctrl |= CPU_CONTROL_V6_EXTPAGE;
2507239268Sgonzo
2508239268Sgonzo	/* Clear out the cache */
2509239268Sgonzo	cpu_idcache_wbinv_all();
2510239268Sgonzo
2511239268Sgonzo	/* Set the control register */
2512239268Sgonzo	ctrl = cpuctrl;
2513239268Sgonzo	cpu_control(0xFFFFFFFF, cpuctrl);
2514239268Sgonzo
2515239268Sgonzo	/* And again. */
2516239268Sgonzo	cpu_idcache_wbinv_all();
2517239268Sgonzo}
2518239268Sgonzo#endif /* CPU_MV_PJ4B */
2519239268Sgonzo
2520239268Sgonzo#ifdef CPU_CORTEXA
2521239268Sgonzo
2522239268Sgonzovoid
2523239268Sgonzocortexa_setup(char *args)
2524239268Sgonzo{
2525239268Sgonzo	int cpuctrl, cpuctrlmask;
2526239268Sgonzo
2527239268Sgonzo	cpuctrlmask = CPU_CONTROL_MMU_ENABLE |     /* MMU enable         [0] */
2528239268Sgonzo	    CPU_CONTROL_AFLT_ENABLE |    /* Alignment fault    [1] */
2529239268Sgonzo	    CPU_CONTROL_DC_ENABLE |      /* DCache enable      [2] */
2530239268Sgonzo	    CPU_CONTROL_BPRD_ENABLE |    /* Branch prediction [11] */
2531239268Sgonzo	    CPU_CONTROL_IC_ENABLE |      /* ICache enable     [12] */
2532239268Sgonzo	    CPU_CONTROL_VECRELOC;        /* Vector relocation [13] */
2533239268Sgonzo
2534239268Sgonzo	cpuctrl = CPU_CONTROL_MMU_ENABLE |
2535239268Sgonzo	    CPU_CONTROL_IC_ENABLE |
2536239268Sgonzo	    CPU_CONTROL_DC_ENABLE |
2537239268Sgonzo	    CPU_CONTROL_BPRD_ENABLE;
2538239268Sgonzo
2539239268Sgonzo#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2540239268Sgonzo	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2541239268Sgonzo#endif
2542239268Sgonzo
2543239268Sgonzo	/* Switch to big endian */
2544239268Sgonzo#ifdef __ARMEB__
2545239268Sgonzo	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2546239268Sgonzo#endif
2547239268Sgonzo
2548239268Sgonzo	/* Check if the vector page is at the high address (0xffff0000) */
2549239268Sgonzo	if (vector_page == ARM_VECTORS_HIGH)
2550239268Sgonzo		cpuctrl |= CPU_CONTROL_VECRELOC;
2551239268Sgonzo
2552239268Sgonzo	/* Clear out the cache */
2553239268Sgonzo	cpu_idcache_wbinv_all();
2554239268Sgonzo
2555239268Sgonzo	/* Set the control register */
2556239268Sgonzo	ctrl = cpuctrl;
2557239268Sgonzo	cpu_control(cpuctrlmask, cpuctrl);
2558239268Sgonzo
2559239268Sgonzo	/* And again. */
2560239268Sgonzo	cpu_idcache_wbinv_all();
2561239268Sgonzo#ifdef SMP
2562239268Sgonzo	armv7_auxctrl((1 << 6) | (1 << 0), (1 << 6) | (1 << 0)); /* Enable SMP + TLB broadcasting  */
2563239268Sgonzo#endif
2564239268Sgonzo}
2565239268Sgonzo#endif  /* CPU_CORTEXA */
2566239268Sgonzo
2567239268Sgonzo
2568129198Scognet#ifdef CPU_SA110
2569129198Scognetstruct cpu_option sa110_options[] = {
2570129198Scognet#ifdef COMPAT_12
2571129198Scognet	{ "nocache",		IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2572129198Scognet	{ "nowritebuf",		IGN, BIC, CPU_CONTROL_WBUF_ENABLE },
2573129198Scognet#endif	/* COMPAT_12 */
2574129198Scognet	{ "cpu.cache",		BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2575129198Scognet	{ "cpu.nocache",	OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2576129198Scognet	{ "sa110.cache",	BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2577129198Scognet	{ "sa110.icache",	BIC, OR,  CPU_CONTROL_IC_ENABLE },
2578129198Scognet	{ "sa110.dcache",	BIC, OR,  CPU_CONTROL_DC_ENABLE },
2579129198Scognet	{ "cpu.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2580129198Scognet	{ "cpu.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
2581129198Scognet	{ "sa110.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2582129198Scognet	{ NULL,			IGN, IGN, 0 }
2583129198Scognet};
2584129198Scognet
2585129198Scognetvoid
2586129198Scognetsa110_setup(args)
2587129198Scognet	char *args;
2588129198Scognet{
2589129198Scognet	int cpuctrl, cpuctrlmask;
2590129198Scognet
2591129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2592129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2593129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2594129198Scognet		 | CPU_CONTROL_WBUF_ENABLE;
2595129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2596129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2597129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2598129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
2599129198Scognet		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
2600129198Scognet		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
2601129198Scognet		 | CPU_CONTROL_CPCLK;
2602129198Scognet
2603129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2604129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2605129198Scognet#endif
2606129198Scognet
2607129198Scognet	cpuctrl = parse_cpu_options(args, sa110_options, cpuctrl);
2608129198Scognet
2609129198Scognet#ifdef __ARMEB__
2610129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2611129198Scognet#endif
2612129198Scognet
2613129198Scognet	/* Clear out the cache */
2614129198Scognet	cpu_idcache_wbinv_all();
2615129198Scognet
2616129198Scognet	/* Set the control register */
2617129198Scognet	ctrl = cpuctrl;
2618129198Scognet/*	cpu_control(cpuctrlmask, cpuctrl);*/
2619129198Scognet	cpu_control(0xffffffff, cpuctrl);
2620129198Scognet
2621236991Simp	/*
2622129198Scognet	 * enable clockswitching, note that this doesn't read or write to r0,
2623129198Scognet	 * r0 is just to make it valid asm
2624129198Scognet	 */
2625129198Scognet	__asm ("mcr 15, 0, r0, c15, c1, 2");
2626129198Scognet}
2627129198Scognet#endif	/* CPU_SA110 */
2628129198Scognet
2629129198Scognet#if defined(CPU_SA1100) || defined(CPU_SA1110)
2630129198Scognetstruct cpu_option sa11x0_options[] = {
2631129198Scognet#ifdef COMPAT_12
2632129198Scognet	{ "nocache",		IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2633129198Scognet	{ "nowritebuf",		IGN, BIC, CPU_CONTROL_WBUF_ENABLE },
2634129198Scognet#endif	/* COMPAT_12 */
2635129198Scognet	{ "cpu.cache",		BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2636129198Scognet	{ "cpu.nocache",	OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2637129198Scognet	{ "sa11x0.cache",	BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2638129198Scognet	{ "sa11x0.icache",	BIC, OR,  CPU_CONTROL_IC_ENABLE },
2639129198Scognet	{ "sa11x0.dcache",	BIC, OR,  CPU_CONTROL_DC_ENABLE },
2640129198Scognet	{ "cpu.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2641129198Scognet	{ "cpu.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
2642129198Scognet	{ "sa11x0.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2643129198Scognet	{ NULL,			IGN, IGN, 0 }
2644129198Scognet};
2645129198Scognet
2646129198Scognetvoid
2647129198Scognetsa11x0_setup(args)
2648129198Scognet	char *args;
2649129198Scognet{
2650129198Scognet	int cpuctrl, cpuctrlmask;
2651129198Scognet
2652129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2653129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2654129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2655129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE;
2656129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2657129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2658129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2659129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
2660129198Scognet		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
2661129198Scognet		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
2662129198Scognet		 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC;
2663129198Scognet
2664129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2665129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2666129198Scognet#endif
2667129198Scognet
2668129198Scognet
2669129198Scognet	cpuctrl = parse_cpu_options(args, sa11x0_options, cpuctrl);
2670129198Scognet
2671129198Scognet#ifdef __ARMEB__
2672129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2673129198Scognet#endif
2674129198Scognet
2675129198Scognet	if (vector_page == ARM_VECTORS_HIGH)
2676129198Scognet		cpuctrl |= CPU_CONTROL_VECRELOC;
2677129198Scognet	/* Clear out the cache */
2678129198Scognet	cpu_idcache_wbinv_all();
2679236991Simp	/* Set the control register */
2680129198Scognet	ctrl = cpuctrl;
2681129198Scognet	cpu_control(0xffffffff, cpuctrl);
2682129198Scognet}
2683129198Scognet#endif	/* CPU_SA1100 || CPU_SA1110 */
2684129198Scognet
2685207611Skevlo#if defined(CPU_FA526) || defined(CPU_FA626TE)
2686201468Srpaulostruct cpu_option fa526_options[] = {
2687201468Srpaulo#ifdef COMPAT_12
2688201468Srpaulo	{ "nocache",		IGN, BIC, (CPU_CONTROL_IC_ENABLE |
2689201468Srpaulo					   CPU_CONTROL_DC_ENABLE) },
2690201468Srpaulo	{ "nowritebuf",		IGN, BIC, CPU_CONTROL_WBUF_ENABLE },
2691201468Srpaulo#endif	/* COMPAT_12 */
2692201468Srpaulo	{ "cpu.cache",		BIC, OR,  (CPU_CONTROL_IC_ENABLE |
2693201468Srpaulo					   CPU_CONTROL_DC_ENABLE) },
2694201468Srpaulo	{ "cpu.nocache",	OR,  BIC, (CPU_CONTROL_IC_ENABLE |
2695201468Srpaulo					   CPU_CONTROL_DC_ENABLE) },
2696201468Srpaulo	{ "cpu.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2697201468Srpaulo	{ "cpu.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
2698201468Srpaulo	{ NULL,			IGN, IGN, 0 }
2699201468Srpaulo};
2700201468Srpaulo
2701201468Srpaulovoid
2702201468Srpaulofa526_setup(char *args)
2703201468Srpaulo{
2704201468Srpaulo	int cpuctrl, cpuctrlmask;
2705201468Srpaulo
2706201468Srpaulo	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2707201468Srpaulo		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2708201468Srpaulo		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2709204122Skevlo		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
2710204122Skevlo		| CPU_CONTROL_BPRD_ENABLE;
2711201468Srpaulo	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2712201468Srpaulo		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2713201468Srpaulo		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2714201468Srpaulo		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
2715201468Srpaulo		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
2716201468Srpaulo		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
2717201468Srpaulo		 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC;
2718201468Srpaulo
2719201468Srpaulo#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2720201468Srpaulo	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2721201468Srpaulo#endif
2722201468Srpaulo
2723201468Srpaulo	cpuctrl = parse_cpu_options(args, fa526_options, cpuctrl);
2724201468Srpaulo
2725201468Srpaulo#ifdef __ARMEB__
2726201468Srpaulo	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2727201468Srpaulo#endif
2728201468Srpaulo
2729201468Srpaulo	if (vector_page == ARM_VECTORS_HIGH)
2730201468Srpaulo		cpuctrl |= CPU_CONTROL_VECRELOC;
2731201468Srpaulo
2732201468Srpaulo	/* Clear out the cache */
2733201468Srpaulo	cpu_idcache_wbinv_all();
2734201468Srpaulo
2735201468Srpaulo	/* Set the control register */
2736201468Srpaulo	ctrl = cpuctrl;
2737201468Srpaulo	cpu_control(0xffffffff, cpuctrl);
2738201468Srpaulo}
2739207611Skevlo#endif	/* CPU_FA526 || CPU_FA626TE */
2740201468Srpaulo
2741201468Srpaulo
2742129198Scognet#if defined(CPU_IXP12X0)
2743129198Scognetstruct cpu_option ixp12x0_options[] = {
2744129198Scognet	{ "cpu.cache",		BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2745129198Scognet	{ "cpu.nocache",	OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2746129198Scognet	{ "ixp12x0.cache",	BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2747129198Scognet	{ "ixp12x0.icache",	BIC, OR,  CPU_CONTROL_IC_ENABLE },
2748129198Scognet	{ "ixp12x0.dcache",	BIC, OR,  CPU_CONTROL_DC_ENABLE },
2749129198Scognet	{ "cpu.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2750129198Scognet	{ "cpu.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
2751129198Scognet	{ "ixp12x0.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2752129198Scognet	{ NULL,			IGN, IGN, 0 }
2753129198Scognet};
2754129198Scognet
2755129198Scognetvoid
2756129198Scognetixp12x0_setup(args)
2757129198Scognet	char *args;
2758129198Scognet{
2759129198Scognet	int cpuctrl, cpuctrlmask;
2760129198Scognet
2761129198Scognet
2762129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE
2763129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_SYST_ENABLE
2764129198Scognet		 | CPU_CONTROL_IC_ENABLE;
2765129198Scognet
2766129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_AFLT_ENABLE
2767129198Scognet		 | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE
2768129198Scognet		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_SYST_ENABLE
2769129198Scognet		 | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_IC_ENABLE
2770129198Scognet		 | CPU_CONTROL_VECRELOC;
2771129198Scognet
2772129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2773129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2774129198Scognet#endif
2775129198Scognet
2776129198Scognet	cpuctrl = parse_cpu_options(args, ixp12x0_options, cpuctrl);
2777129198Scognet
2778129198Scognet#ifdef __ARMEB__
2779129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2780129198Scognet#endif
2781129198Scognet
2782129198Scognet	if (vector_page == ARM_VECTORS_HIGH)
2783129198Scognet		cpuctrl |= CPU_CONTROL_VECRELOC;
2784129198Scognet
2785129198Scognet	/* Clear out the cache */
2786129198Scognet	cpu_idcache_wbinv_all();
2787129198Scognet
2788236991Simp	/* Set the control register */
2789129198Scognet	ctrl = cpuctrl;
2790129198Scognet	/* cpu_control(0xffffffff, cpuctrl); */
2791129198Scognet	cpu_control(cpuctrlmask, cpuctrl);
2792129198Scognet}
2793129198Scognet#endif /* CPU_IXP12X0 */
2794129198Scognet
2795129198Scognet#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
2796161592Scognet  defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
2797164080Scognet  defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)
2798129198Scognetstruct cpu_option xscale_options[] = {
2799129198Scognet#ifdef COMPAT_12
2800129198Scognet	{ "branchpredict", 	BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
2801129198Scognet	{ "nocache",		IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2802129198Scognet#endif	/* COMPAT_12 */
2803129198Scognet	{ "cpu.branchpredict", 	BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
2804129198Scognet	{ "cpu.cache",		BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2805129198Scognet	{ "cpu.nocache",	OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2806129198Scognet	{ "xscale.branchpredict", BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
2807129198Scognet	{ "xscale.cache",	BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2808129198Scognet	{ "xscale.icache",	BIC, OR,  CPU_CONTROL_IC_ENABLE },
2809129198Scognet	{ "xscale.dcache",	BIC, OR,  CPU_CONTROL_DC_ENABLE },
2810129198Scognet	{ NULL,			IGN, IGN, 0 }
2811129198Scognet};
2812129198Scognet
2813129198Scognetvoid
2814129198Scognetxscale_setup(args)
2815129198Scognet	char *args;
2816129198Scognet{
2817129198Scognet	uint32_t auxctl;
2818129198Scognet	int cpuctrl, cpuctrlmask;
2819129198Scognet
2820129198Scognet	/*
2821129198Scognet	 * The XScale Write Buffer is always enabled.  Our option
2822129198Scognet	 * is to enable/disable coalescing.  Note that bits 6:3
2823129198Scognet	 * must always be enabled.
2824129198Scognet	 */
2825129198Scognet
2826129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2827129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2828129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2829129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
2830129198Scognet		 | CPU_CONTROL_BPRD_ENABLE;
2831129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2832129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2833129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2834129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
2835129198Scognet		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
2836129198Scognet		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
2837171618Scognet		 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC | \
2838171618Scognet		 CPU_CONTROL_L2_ENABLE;
2839129198Scognet
2840129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2841129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2842129198Scognet#endif
2843129198Scognet
2844129198Scognet	cpuctrl = parse_cpu_options(args, xscale_options, cpuctrl);
2845129198Scognet
2846129198Scognet#ifdef __ARMEB__
2847129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2848129198Scognet#endif
2849129198Scognet
2850129198Scognet	if (vector_page == ARM_VECTORS_HIGH)
2851129198Scognet		cpuctrl |= CPU_CONTROL_VECRELOC;
2852171618Scognet#ifdef CPU_XSCALE_CORE3
2853171618Scognet	cpuctrl |= CPU_CONTROL_L2_ENABLE;
2854171618Scognet#endif
2855129198Scognet
2856129198Scognet	/* Clear out the cache */
2857129198Scognet	cpu_idcache_wbinv_all();
2858129198Scognet
2859129198Scognet	/*
2860129198Scognet	 * Set the control register.  Note that bits 6:3 must always
2861129198Scognet	 * be set to 1.
2862129198Scognet	 */
2863129198Scognet	ctrl = cpuctrl;
2864129198Scognet/*	cpu_control(cpuctrlmask, cpuctrl);*/
2865129198Scognet	cpu_control(0xffffffff, cpuctrl);
2866129198Scognet
2867129198Scognet	/* Make sure write coalescing is turned on */
2868129198Scognet	__asm __volatile("mrc p15, 0, %0, c1, c0, 1"
2869129198Scognet		: "=r" (auxctl));
2870129198Scognet#ifdef XSCALE_NO_COALESCE_WRITES
2871129198Scognet	auxctl |= XSCALE_AUXCTL_K;
2872129198Scognet#else
2873129198Scognet	auxctl &= ~XSCALE_AUXCTL_K;
2874129198Scognet#endif
2875171618Scognet#ifdef CPU_XSCALE_CORE3
2876171618Scognet	auxctl |= XSCALE_AUXCTL_LLR;
2877171618Scognet	auxctl |= XSCALE_AUXCTL_MD_MASK;
2878171618Scognet#endif
2879129198Scognet	__asm __volatile("mcr p15, 0, %0, c1, c0, 1"
2880129198Scognet		: : "r" (auxctl));
2881129198Scognet}
2882236991Simp#endif	/* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425
2883161592Scognet	   CPU_XSCALE_80219 */
2884