cpufunc.c revision 295096
1129198Scognet/*	$NetBSD: cpufunc.c,v 1.65 2003/11/05 12:53:15 scw Exp $	*/
2129198Scognet
3139735Simp/*-
4129198Scognet * arm9 support code Copyright (C) 2001 ARM Ltd
5129198Scognet * Copyright (c) 1997 Mark Brinicombe.
6129198Scognet * Copyright (c) 1997 Causality Limited
7129198Scognet * All rights reserved.
8129198Scognet *
9129198Scognet * Redistribution and use in source and binary forms, with or without
10129198Scognet * modification, are permitted provided that the following conditions
11129198Scognet * are met:
12129198Scognet * 1. Redistributions of source code must retain the above copyright
13129198Scognet *    notice, this list of conditions and the following disclaimer.
14129198Scognet * 2. Redistributions in binary form must reproduce the above copyright
15129198Scognet *    notice, this list of conditions and the following disclaimer in the
16129198Scognet *    documentation and/or other materials provided with the distribution.
17129198Scognet * 3. All advertising materials mentioning features or use of this software
18129198Scognet *    must display the following acknowledgement:
19129198Scognet *	This product includes software developed by Causality Limited.
20129198Scognet * 4. The name of Causality Limited may not be used to endorse or promote
21129198Scognet *    products derived from this software without specific prior written
22129198Scognet *    permission.
23129198Scognet *
24129198Scognet * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
25129198Scognet * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26129198Scognet * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27129198Scognet * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
28129198Scognet * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29129198Scognet * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30129198Scognet * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31129198Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32129198Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33129198Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34129198Scognet * SUCH DAMAGE.
35129198Scognet *
36129198Scognet * RiscBSD kernel project
37129198Scognet *
38129198Scognet * cpufuncs.c
39129198Scognet *
40129198Scognet * C functions for supporting CPU / MMU / TLB specific operations.
41129198Scognet *
42129198Scognet * Created      : 30/01/97
43129198Scognet */
44129198Scognet#include <sys/cdefs.h>
45129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/cpufunc.c 295096 2016-01-31 16:34:06Z mmel $");
46129198Scognet
47129198Scognet#include <sys/param.h>
48129198Scognet#include <sys/systm.h>
49129198Scognet#include <sys/lock.h>
50129198Scognet#include <sys/mutex.h>
51132472Scognet#include <sys/bus.h>
52132472Scognet#include <machine/bus.h>
53129198Scognet#include <machine/cpu.h>
54129198Scognet#include <machine/disassem.h>
55129198Scognet
56129198Scognet#include <vm/vm.h>
57129198Scognet#include <vm/pmap.h>
58166655Scognet#include <vm/uma.h>
59129198Scognet
60129198Scognet#include <machine/cpuconf.h>
61129198Scognet#include <machine/cpufunc.h>
62129198Scognet
63161592Scognet#if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219)
64135646Scognet#include <arm/xscale/i80321/i80321reg.h>
65135646Scognet#include <arm/xscale/i80321/i80321var.h>
66129198Scognet#endif
67129198Scognet
68243579Smarcel/*
69243579Smarcel * Some definitions in i81342reg.h clash with i80321reg.h.
70243579Smarcel * This only happens for the LINT kernel. As it happens,
71243579Smarcel * we don't need anything from i81342reg.h that we already
72243579Smarcel * got from somewhere else during a LINT compile.
73243579Smarcel */
74243579Smarcel#if defined(CPU_XSCALE_81342) && !defined(COMPILING_LINT)
75164080Scognet#include <arm/xscale/i8134x/i81342reg.h>
76164080Scognet#endif
77164080Scognet
78129198Scognet#ifdef CPU_XSCALE_IXP425
79135646Scognet#include <arm/xscale/ixp425/ixp425reg.h>
80135646Scognet#include <arm/xscale/ixp425/ixp425var.h>
81129198Scognet#endif
82129198Scognet
83129198Scognet/* PRIMARY CACHE VARIABLES */
84129198Scognetint	arm_picache_size;
85129198Scognetint	arm_picache_line_size;
86129198Scognetint	arm_picache_ways;
87129198Scognet
88129198Scognetint	arm_pdcache_size;	/* and unified */
89129198Scognetint	arm_pdcache_line_size;
90129198Scognetint	arm_pdcache_ways;
91129198Scognet
92129198Scognetint	arm_pcache_type;
93129198Scognetint	arm_pcache_unified;
94129198Scognet
95129198Scognetint	arm_dcache_align;
96129198Scognetint	arm_dcache_align_mask;
97129198Scognet
98239268Sgonzou_int	arm_cache_level;
99239268Sgonzou_int	arm_cache_type[14];
100239268Sgonzou_int	arm_cache_loc;
101239268Sgonzo
102129198Scognetint ctrl;
103129198Scognet
104129198Scognet#ifdef CPU_ARM9
105129198Scognetstruct cpu_functions arm9_cpufuncs = {
106129198Scognet	/* CPU functions */
107129198Scognet
108129198Scognet	cpufunc_nullop,			/* cpwait		*/
109129198Scognet
110129198Scognet	/* MMU functions */
111129198Scognet
112129198Scognet	cpufunc_control,		/* control		*/
113129198Scognet	arm9_setttb,			/* Setttb		*/
114129198Scognet
115129198Scognet	/* TLB functions */
116129198Scognet
117129198Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
118129198Scognet	arm9_tlb_flushID_SE,		/* tlb_flushID_SE	*/
119129198Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
120129198Scognet	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
121129198Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
122129198Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
123129198Scognet
124129198Scognet	/* Cache operations */
125129198Scognet
126146605Scognet	arm9_icache_sync_all,		/* icache_sync_all	*/
127146605Scognet	arm9_icache_sync_range,		/* icache_sync_range	*/
128129198Scognet
129146605Scognet	arm9_dcache_wbinv_all,		/* dcache_wbinv_all	*/
130146605Scognet	arm9_dcache_wbinv_range,	/* dcache_wbinv_range	*/
131195798Sraj	arm9_dcache_inv_range,		/* dcache_inv_range	*/
132146605Scognet	arm9_dcache_wb_range,		/* dcache_wb_range	*/
133129198Scognet
134262420Sian	armv4_idcache_inv_all,		/* idcache_inv_all	*/
135146605Scognet	arm9_idcache_wbinv_all,		/* idcache_wbinv_all	*/
136146605Scognet	arm9_idcache_wbinv_range,	/* idcache_wbinv_range	*/
137171618Scognet	cpufunc_nullop,			/* l2cache_wbinv_all	*/
138171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
139171781Scognet	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
140171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
141265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
142129198Scognet
143129198Scognet	/* Other functions */
144129198Scognet
145129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
146129198Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
147129198Scognet
148129198Scognet	(void *)cpufunc_nullop,		/* sleep		*/
149129198Scognet
150129198Scognet	/* Soft functions */
151129198Scognet
152129198Scognet	arm9_context_switch,		/* context_switch	*/
153129198Scognet
154129198Scognet	arm9_setup			/* cpu setup		*/
155129198Scognet
156129198Scognet};
157129198Scognet#endif /* CPU_ARM9 */
158129198Scognet
159280809Sandrew#if defined(CPU_ARM9E)
160172738Simpstruct cpu_functions armv5_ec_cpufuncs = {
161172738Simp	/* CPU functions */
162172738Simp
163172738Simp	cpufunc_nullop,			/* cpwait		*/
164172738Simp
165172738Simp	/* MMU functions */
166172738Simp
167172738Simp	cpufunc_control,		/* control		*/
168172738Simp	armv5_ec_setttb,		/* Setttb		*/
169172738Simp
170172738Simp	/* TLB functions */
171172738Simp
172172738Simp	armv4_tlb_flushID,		/* tlb_flushID		*/
173172738Simp	arm10_tlb_flushID_SE,		/* tlb_flushID_SE	*/
174172738Simp	armv4_tlb_flushI,		/* tlb_flushI		*/
175172738Simp	arm10_tlb_flushI_SE,		/* tlb_flushI_SE	*/
176172738Simp	armv4_tlb_flushD,		/* tlb_flushD		*/
177172738Simp	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
178172738Simp
179172738Simp	/* Cache operations */
180172738Simp
181172738Simp	armv5_ec_icache_sync_all,	/* icache_sync_all	*/
182172738Simp	armv5_ec_icache_sync_range,	/* icache_sync_range	*/
183172738Simp
184172738Simp	armv5_ec_dcache_wbinv_all,	/* dcache_wbinv_all	*/
185172738Simp	armv5_ec_dcache_wbinv_range,	/* dcache_wbinv_range	*/
186195798Sraj	armv5_ec_dcache_inv_range,	/* dcache_inv_range	*/
187172738Simp	armv5_ec_dcache_wb_range,	/* dcache_wb_range	*/
188172738Simp
189262420Sian	armv4_idcache_inv_all,		/* idcache_inv_all	*/
190172738Simp	armv5_ec_idcache_wbinv_all,	/* idcache_wbinv_all	*/
191172738Simp	armv5_ec_idcache_wbinv_range,	/* idcache_wbinv_range	*/
192172738Simp
193173442Scognet	cpufunc_nullop,                 /* l2cache_wbinv_all    */
194173442Scognet	(void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
195173442Scognet      	(void *)cpufunc_nullop,         /* l2cache_inv_range    */
196173442Scognet	(void *)cpufunc_nullop,         /* l2cache_wb_range     */
197265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
198236991Simp
199172738Simp	/* Other functions */
200172738Simp
201172738Simp	cpufunc_nullop,			/* flush_prefetchbuf	*/
202172738Simp	armv4_drain_writebuf,		/* drain_writebuf	*/
203172738Simp
204172738Simp	(void *)cpufunc_nullop,		/* sleep		*/
205172738Simp
206172738Simp	/* Soft functions */
207172738Simp
208172738Simp	arm10_context_switch,		/* context_switch	*/
209172738Simp
210172738Simp	arm10_setup			/* cpu setup		*/
211172738Simp
212172738Simp};
213183835Sraj
214186933Srajstruct cpu_functions sheeva_cpufuncs = {
215183835Sraj	/* CPU functions */
216183835Sraj
217183835Sraj	cpufunc_nullop,			/* cpwait		*/
218183835Sraj
219183835Sraj	/* MMU functions */
220183835Sraj
221183835Sraj	cpufunc_control,		/* control		*/
222186933Sraj	sheeva_setttb,			/* Setttb		*/
223183835Sraj
224183835Sraj	/* TLB functions */
225183835Sraj
226183835Sraj	armv4_tlb_flushID,		/* tlb_flushID		*/
227183835Sraj	arm10_tlb_flushID_SE,		/* tlb_flushID_SE	*/
228183835Sraj	armv4_tlb_flushI,		/* tlb_flushI		*/
229183835Sraj	arm10_tlb_flushI_SE,		/* tlb_flushI_SE	*/
230183835Sraj	armv4_tlb_flushD,		/* tlb_flushD		*/
231183835Sraj	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
232183835Sraj
233183835Sraj	/* Cache operations */
234183835Sraj
235183835Sraj	armv5_ec_icache_sync_all,	/* icache_sync_all	*/
236183835Sraj	armv5_ec_icache_sync_range,	/* icache_sync_range	*/
237183835Sraj
238183835Sraj	armv5_ec_dcache_wbinv_all,	/* dcache_wbinv_all	*/
239186933Sraj	sheeva_dcache_wbinv_range,	/* dcache_wbinv_range	*/
240186933Sraj	sheeva_dcache_inv_range,	/* dcache_inv_range	*/
241186933Sraj	sheeva_dcache_wb_range,		/* dcache_wb_range	*/
242183835Sraj
243262420Sian	armv4_idcache_inv_all,		/* idcache_inv_all	*/
244183835Sraj	armv5_ec_idcache_wbinv_all,	/* idcache_wbinv_all	*/
245186933Sraj	sheeva_idcache_wbinv_range,	/* idcache_wbinv_all	*/
246183835Sraj
247186933Sraj	sheeva_l2cache_wbinv_all,	/* l2cache_wbinv_all    */
248186933Sraj	sheeva_l2cache_wbinv_range,	/* l2cache_wbinv_range  */
249186933Sraj	sheeva_l2cache_inv_range,	/* l2cache_inv_range    */
250186933Sraj	sheeva_l2cache_wb_range,	/* l2cache_wb_range     */
251265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
252183835Sraj
253183835Sraj	/* Other functions */
254183835Sraj
255183835Sraj	cpufunc_nullop,			/* flush_prefetchbuf	*/
256183835Sraj	armv4_drain_writebuf,		/* drain_writebuf	*/
257183835Sraj
258212825Smav	sheeva_cpu_sleep,		/* sleep		*/
259183835Sraj
260183835Sraj	/* Soft functions */
261183835Sraj
262183835Sraj	arm10_context_switch,		/* context_switch	*/
263183835Sraj
264183835Sraj	arm10_setup			/* cpu setup		*/
265183835Sraj};
266280809Sandrew#endif /* CPU_ARM9E */
267172738Simp
268239268Sgonzo#ifdef CPU_MV_PJ4B
269239268Sgonzostruct cpu_functions pj4bv7_cpufuncs = {
270239268Sgonzo	/* CPU functions */
271239268Sgonzo
272266672Szbb	armv7_drain_writebuf,		/* cpwait		*/
273239268Sgonzo
274239268Sgonzo	/* MMU functions */
275239268Sgonzo
276239268Sgonzo	cpufunc_control,		/* control		*/
277266672Szbb	armv7_setttb,			/* Setttb		*/
278239268Sgonzo
279239268Sgonzo	/* TLB functions */
280239268Sgonzo
281239268Sgonzo	armv7_tlb_flushID,		/* tlb_flushID		*/
282239268Sgonzo	armv7_tlb_flushID_SE,		/* tlb_flushID_SE	*/
283239268Sgonzo	armv7_tlb_flushID,		/* tlb_flushI		*/
284239268Sgonzo	armv7_tlb_flushID_SE,		/* tlb_flushI_SE	*/
285239268Sgonzo	armv7_tlb_flushID,		/* tlb_flushD		*/
286239268Sgonzo	armv7_tlb_flushID_SE,		/* tlb_flushD_SE	*/
287239268Sgonzo
288239268Sgonzo	/* Cache operations */
289239268Sgonzo	armv7_idcache_wbinv_all,	/* icache_sync_all	*/
290239268Sgonzo	armv7_icache_sync_range,	/* icache_sync_range	*/
291239268Sgonzo
292239268Sgonzo	armv7_dcache_wbinv_all,		/* dcache_wbinv_all	*/
293239268Sgonzo	armv7_dcache_wbinv_range,	/* dcache_wbinv_range	*/
294239268Sgonzo	armv7_dcache_inv_range,		/* dcache_inv_range	*/
295239268Sgonzo	armv7_dcache_wb_range,		/* dcache_wb_range	*/
296239268Sgonzo
297262420Sian	armv7_idcache_inv_all,		/* idcache_inv_all	*/
298239268Sgonzo	armv7_idcache_wbinv_all,	/* idcache_wbinv_all	*/
299239268Sgonzo	armv7_idcache_wbinv_range,	/* idcache_wbinv_all	*/
300239268Sgonzo
301239268Sgonzo	(void *)cpufunc_nullop,		/* l2cache_wbinv_all	*/
302239268Sgonzo	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
303239268Sgonzo	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
304239268Sgonzo	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
305265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
306239268Sgonzo
307239268Sgonzo	/* Other functions */
308239268Sgonzo
309266672Szbb	cpufunc_nullop,			/* flush_prefetchbuf	*/
310266672Szbb	armv7_drain_writebuf,		/* drain_writebuf	*/
311239268Sgonzo
312239268Sgonzo	(void *)cpufunc_nullop,		/* sleep		*/
313239268Sgonzo
314239268Sgonzo	/* Soft functions */
315266672Szbb	armv7_context_switch,		/* context_switch	*/
316239268Sgonzo
317239268Sgonzo	pj4bv7_setup			/* cpu setup		*/
318239268Sgonzo};
319239268Sgonzo#endif /* CPU_MV_PJ4B */
320239268Sgonzo
321280847Sandrew#if defined(CPU_XSCALE_80321) || \
322161592Scognet  defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
323161592Scognet  defined(CPU_XSCALE_80219)
324161592Scognet
325129198Scognetstruct cpu_functions xscale_cpufuncs = {
326129198Scognet	/* CPU functions */
327283366Sandrew
328129198Scognet	xscale_cpwait,			/* cpwait		*/
329129198Scognet
330129198Scognet	/* MMU functions */
331129198Scognet
332129198Scognet	xscale_control,			/* control		*/
333129198Scognet	xscale_setttb,			/* setttb		*/
334129198Scognet
335129198Scognet	/* TLB functions */
336129198Scognet
337129198Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
338129198Scognet	xscale_tlb_flushID_SE,		/* tlb_flushID_SE	*/
339129198Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
340129198Scognet	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
341129198Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
342129198Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
343129198Scognet
344129198Scognet	/* Cache operations */
345129198Scognet
346129198Scognet	xscale_cache_syncI,		/* icache_sync_all	*/
347129198Scognet	xscale_cache_syncI_rng,		/* icache_sync_range	*/
348129198Scognet
349129198Scognet	xscale_cache_purgeD,		/* dcache_wbinv_all	*/
350129198Scognet	xscale_cache_purgeD_rng,	/* dcache_wbinv_range	*/
351129198Scognet	xscale_cache_flushD_rng,	/* dcache_inv_range	*/
352129198Scognet	xscale_cache_cleanD_rng,	/* dcache_wb_range	*/
353129198Scognet
354262420Sian	xscale_cache_flushID,		/* idcache_inv_all	*/
355129198Scognet	xscale_cache_purgeID,		/* idcache_wbinv_all	*/
356129198Scognet	xscale_cache_purgeID_rng,	/* idcache_wbinv_range	*/
357171618Scognet	cpufunc_nullop,			/* l2cache_wbinv_all 	*/
358171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
359171781Scognet	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
360171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
361265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
362129198Scognet
363129198Scognet	/* Other functions */
364129198Scognet
365129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
366129198Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
367129198Scognet
368129198Scognet	xscale_cpu_sleep,		/* sleep		*/
369129198Scognet
370129198Scognet	/* Soft functions */
371129198Scognet
372129198Scognet	xscale_context_switch,		/* context_switch	*/
373129198Scognet
374129198Scognet	xscale_setup			/* cpu setup		*/
375129198Scognet};
376129198Scognet#endif
377280847Sandrew/* CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425
378161592Scognet   CPU_XSCALE_80219 */
379129198Scognet
380164080Scognet#ifdef CPU_XSCALE_81342
381164080Scognetstruct cpu_functions xscalec3_cpufuncs = {
382164080Scognet	/* CPU functions */
383283366Sandrew
384164080Scognet	xscale_cpwait,			/* cpwait		*/
385164080Scognet
386164080Scognet	/* MMU functions */
387164080Scognet
388164080Scognet	xscale_control,			/* control		*/
389164080Scognet	xscalec3_setttb,		/* setttb		*/
390164080Scognet
391164080Scognet	/* TLB functions */
392164080Scognet
393164080Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
394164080Scognet	xscale_tlb_flushID_SE,		/* tlb_flushID_SE	*/
395164080Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
396164080Scognet	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
397164080Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
398164080Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
399164080Scognet
400164080Scognet	/* Cache operations */
401164080Scognet
402164080Scognet	xscalec3_cache_syncI,		/* icache_sync_all	*/
403171618Scognet	xscalec3_cache_syncI_rng,	/* icache_sync_range	*/
404164080Scognet
405164080Scognet	xscalec3_cache_purgeD,		/* dcache_wbinv_all	*/
406164080Scognet	xscalec3_cache_purgeD_rng,	/* dcache_wbinv_range	*/
407164080Scognet	xscale_cache_flushD_rng,	/* dcache_inv_range	*/
408164080Scognet	xscalec3_cache_cleanD_rng,	/* dcache_wb_range	*/
409164080Scognet
410262420Sian	xscale_cache_flushID,		/* idcache_inv_all	*/
411171618Scognet	xscalec3_cache_purgeID,		/* idcache_wbinv_all	*/
412164080Scognet	xscalec3_cache_purgeID_rng,	/* idcache_wbinv_range	*/
413171618Scognet	xscalec3_l2cache_purge,		/* l2cache_wbinv_all	*/
414171618Scognet	xscalec3_l2cache_purge_rng,	/* l2cache_wbinv_range	*/
415171618Scognet	xscalec3_l2cache_flush_rng,	/* l2cache_inv_range	*/
416171618Scognet	xscalec3_l2cache_clean_rng,	/* l2cache_wb_range	*/
417265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
418164080Scognet
419164080Scognet	/* Other functions */
420164080Scognet
421164080Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
422164080Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
423164080Scognet
424164080Scognet	xscale_cpu_sleep,		/* sleep		*/
425164080Scognet
426164080Scognet	/* Soft functions */
427164080Scognet
428164080Scognet	xscalec3_context_switch,	/* context_switch	*/
429164080Scognet
430164080Scognet	xscale_setup			/* cpu setup		*/
431164080Scognet};
432164080Scognet#endif /* CPU_XSCALE_81342 */
433201468Srpaulo
434201468Srpaulo
435280842Sandrew#if defined(CPU_FA526)
436201468Srpaulostruct cpu_functions fa526_cpufuncs = {
437201468Srpaulo	/* CPU functions */
438201468Srpaulo
439207611Skevlo	cpufunc_nullop,			/* cpwait		*/
440201468Srpaulo
441201468Srpaulo	/* MMU functions */
442201468Srpaulo
443207611Skevlo	cpufunc_control,		/* control		*/
444207611Skevlo	fa526_setttb,			/* setttb		*/
445201468Srpaulo
446201468Srpaulo	/* TLB functions */
447201468Srpaulo
448207611Skevlo	armv4_tlb_flushID,		/* tlb_flushID		*/
449207611Skevlo	fa526_tlb_flushID_SE,		/* tlb_flushID_SE	*/
450207611Skevlo	armv4_tlb_flushI,		/* tlb_flushI		*/
451207611Skevlo	fa526_tlb_flushI_SE,		/* tlb_flushI_SE	*/
452207611Skevlo	armv4_tlb_flushD,		/* tlb_flushD		*/
453207611Skevlo	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
454201468Srpaulo
455201468Srpaulo	/* Cache operations */
456201468Srpaulo
457207611Skevlo	fa526_icache_sync_all,		/* icache_sync_all	*/
458207611Skevlo	fa526_icache_sync_range,	/* icache_sync_range	*/
459201468Srpaulo
460207611Skevlo	fa526_dcache_wbinv_all,		/* dcache_wbinv_all	*/
461207611Skevlo	fa526_dcache_wbinv_range,	/* dcache_wbinv_range	*/
462207611Skevlo	fa526_dcache_inv_range,		/* dcache_inv_range	*/
463207611Skevlo	fa526_dcache_wb_range,		/* dcache_wb_range	*/
464201468Srpaulo
465262420Sian	armv4_idcache_inv_all,		/* idcache_inv_all	*/
466207611Skevlo	fa526_idcache_wbinv_all,	/* idcache_wbinv_all	*/
467207611Skevlo	fa526_idcache_wbinv_range,	/* idcache_wbinv_range	*/
468207611Skevlo	cpufunc_nullop,			/* l2cache_wbinv_all	*/
469207611Skevlo	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
470207611Skevlo	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
471207611Skevlo	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
472265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
473201468Srpaulo
474201468Srpaulo	/* Other functions */
475201468Srpaulo
476207611Skevlo	fa526_flush_prefetchbuf,	/* flush_prefetchbuf	*/
477207611Skevlo	armv4_drain_writebuf,		/* drain_writebuf	*/
478201468Srpaulo
479207611Skevlo	fa526_cpu_sleep,		/* sleep		*/
480201468Srpaulo
481201468Srpaulo	/* Soft functions */
482201468Srpaulo
483201468Srpaulo
484207611Skevlo	fa526_context_switch,		/* context_switch	*/
485201468Srpaulo
486207611Skevlo	fa526_setup			/* cpu setup 		*/
487236991Simp};
488280842Sandrew#endif	/* CPU_FA526 */
489201468Srpaulo
490244480Sgonzo#if defined(CPU_ARM1176)
491244480Sgonzostruct cpu_functions arm1176_cpufuncs = {
492244480Sgonzo	/* CPU functions */
493283366Sandrew
494244480Sgonzo	cpufunc_nullop,                 /* cpwait               */
495283366Sandrew
496244480Sgonzo	/* MMU functions */
497283366Sandrew
498244480Sgonzo	cpufunc_control,                /* control              */
499244480Sgonzo	arm11x6_setttb,                 /* Setttb               */
500283366Sandrew
501244480Sgonzo	/* TLB functions */
502283366Sandrew
503244480Sgonzo	arm11_tlb_flushID,              /* tlb_flushID          */
504244480Sgonzo	arm11_tlb_flushID_SE,           /* tlb_flushID_SE       */
505244480Sgonzo	arm11_tlb_flushI,               /* tlb_flushI           */
506244480Sgonzo	arm11_tlb_flushI_SE,            /* tlb_flushI_SE        */
507244480Sgonzo	arm11_tlb_flushD,               /* tlb_flushD           */
508244480Sgonzo	arm11_tlb_flushD_SE,            /* tlb_flushD_SE        */
509283366Sandrew
510244480Sgonzo	/* Cache operations */
511283366Sandrew
512244480Sgonzo	arm11x6_icache_sync_all,        /* icache_sync_all      */
513244480Sgonzo	arm11x6_icache_sync_range,      /* icache_sync_range    */
514283366Sandrew
515244480Sgonzo	arm11x6_dcache_wbinv_all,       /* dcache_wbinv_all     */
516244480Sgonzo	armv6_dcache_wbinv_range,       /* dcache_wbinv_range   */
517244480Sgonzo	armv6_dcache_inv_range,         /* dcache_inv_range     */
518244480Sgonzo	armv6_dcache_wb_range,          /* dcache_wb_range      */
519283366Sandrew
520262420Sian	armv6_idcache_inv_all,		/* idcache_inv_all	*/
521244480Sgonzo	arm11x6_idcache_wbinv_all,      /* idcache_wbinv_all    */
522244480Sgonzo	arm11x6_idcache_wbinv_range,    /* idcache_wbinv_range  */
523283366Sandrew
524244480Sgonzo	(void *)cpufunc_nullop,         /* l2cache_wbinv_all    */
525244480Sgonzo	(void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
526244480Sgonzo	(void *)cpufunc_nullop,         /* l2cache_inv_range    */
527244480Sgonzo	(void *)cpufunc_nullop,         /* l2cache_wb_range     */
528265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
529283366Sandrew
530244480Sgonzo	/* Other functions */
531283366Sandrew
532244480Sgonzo	arm11x6_flush_prefetchbuf,      /* flush_prefetchbuf    */
533244480Sgonzo	arm11_drain_writebuf,           /* drain_writebuf       */
534283366Sandrew
535244480Sgonzo	arm11x6_sleep,                  /* sleep                */
536283366Sandrew
537244480Sgonzo	/* Soft functions */
538283366Sandrew
539244480Sgonzo	arm11_context_switch,           /* context_switch       */
540283366Sandrew
541244480Sgonzo	arm11x6_setup                   /* cpu setup            */
542244480Sgonzo};
543244480Sgonzo#endif /*CPU_ARM1176 */
544239701Sgonzo
545259640Sganbold#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
546239268Sgonzostruct cpu_functions cortexa_cpufuncs = {
547239268Sgonzo	/* CPU functions */
548283366Sandrew
549239268Sgonzo	cpufunc_nullop,                 /* cpwait               */
550283366Sandrew
551239268Sgonzo	/* MMU functions */
552283366Sandrew
553239268Sgonzo	cpufunc_control,                /* control              */
554239268Sgonzo	armv7_setttb,                   /* Setttb               */
555283366Sandrew
556283366Sandrew	/*
557263251Sian	 * TLB functions.  ARMv7 does all TLB ops based on a unified TLB model
558263251Sian	 * whether the hardware implements separate I+D or not, so we use the
559263251Sian	 * same 'ID' functions for all 3 variations.
560263251Sian	 */
561283366Sandrew
562243024Scognet	armv7_tlb_flushID,              /* tlb_flushID          */
563239268Sgonzo	armv7_tlb_flushID_SE,           /* tlb_flushID_SE       */
564263251Sian	armv7_tlb_flushID,              /* tlb_flushI           */
565263251Sian	armv7_tlb_flushID_SE,           /* tlb_flushI_SE        */
566263251Sian	armv7_tlb_flushID,              /* tlb_flushD           */
567263251Sian	armv7_tlb_flushID_SE,           /* tlb_flushD_SE        */
568283366Sandrew
569239268Sgonzo	/* Cache operations */
570283366Sandrew
571264994Sian	armv7_icache_sync_all, 	        /* icache_sync_all      */
572239268Sgonzo	armv7_icache_sync_range,        /* icache_sync_range    */
573283366Sandrew
574239268Sgonzo	armv7_dcache_wbinv_all,         /* dcache_wbinv_all     */
575239268Sgonzo	armv7_dcache_wbinv_range,       /* dcache_wbinv_range   */
576239268Sgonzo	armv7_dcache_inv_range,         /* dcache_inv_range     */
577239268Sgonzo	armv7_dcache_wb_range,          /* dcache_wb_range      */
578283366Sandrew
579262420Sian	armv7_idcache_inv_all,		/* idcache_inv_all	*/
580239268Sgonzo	armv7_idcache_wbinv_all,        /* idcache_wbinv_all    */
581239268Sgonzo	armv7_idcache_wbinv_range,      /* idcache_wbinv_range  */
582283366Sandrew
583283366Sandrew	/*
584243026Scognet	 * Note: For CPUs using the PL310 the L2 ops are filled in when the
585239268Sgonzo	 * L2 cache controller is actually enabled.
586239268Sgonzo	 */
587239268Sgonzo	cpufunc_nullop,                 /* l2cache_wbinv_all    */
588239268Sgonzo	(void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
589239268Sgonzo	(void *)cpufunc_nullop,         /* l2cache_inv_range    */
590239268Sgonzo	(void *)cpufunc_nullop,         /* l2cache_wb_range     */
591265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
592283366Sandrew
593239268Sgonzo	/* Other functions */
594283366Sandrew
595239268Sgonzo	cpufunc_nullop,                 /* flush_prefetchbuf    */
596245478Scognet	armv7_drain_writebuf,           /* drain_writebuf       */
597283366Sandrew
598282934Sganbold	armv7_cpu_sleep,                /* sleep                */
599283366Sandrew
600239268Sgonzo	/* Soft functions */
601283366Sandrew
602245478Scognet	armv7_context_switch,           /* context_switch       */
603283366Sandrew
604239268Sgonzo	cortexa_setup                     /* cpu setup            */
605239268Sgonzo};
606239268Sgonzo#endif /* CPU_CORTEXA */
607201468Srpaulo
608129198Scognet/*
609129198Scognet * Global constants also used by locore.s
610129198Scognet */
611129198Scognet
612129198Scognetstruct cpu_functions cpufuncs;
613129198Scognetu_int cputype;
614129198Scognetu_int cpu_reset_needs_v4_MMU_disable;	/* flag used in locore.s */
615129198Scognet
616262958Sian#if defined(CPU_ARM9) ||	\
617280824Sandrew  defined (CPU_ARM9E) ||	\
618280847Sandrew  defined(CPU_ARM1176) || defined(CPU_XSCALE_80321) ||		\
619207611Skevlo  defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) ||		\
620280842Sandrew  defined(CPU_FA526) || defined(CPU_MV_PJ4B) ||			\
621239268Sgonzo  defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \
622259640Sganbold  defined(CPU_CORTEXA) || defined(CPU_KRAIT)
623161592Scognet
624278518Szbb/* Global cache line sizes, use 32 as default */
625278518Szbbint	arm_dcache_min_line_size = 32;
626278518Szbbint	arm_icache_min_line_size = 32;
627278518Szbbint	arm_idcache_min_line_size = 32;
628278518Szbb
629137498Strhodesstatic void get_cachetype_cp15(void);
630129198Scognet
631129198Scognet/* Additional cache information local to this file.  Log2 of some of the
632129198Scognet   above numbers.  */
633129198Scognetstatic int	arm_dcache_l2_nsets;
634129198Scognetstatic int	arm_dcache_l2_assoc;
635129198Scognetstatic int	arm_dcache_l2_linesize;
636129198Scognet
637129198Scognetstatic void
638129198Scognetget_cachetype_cp15()
639129198Scognet{
640239268Sgonzo	u_int ctype, isize, dsize, cpuid;
641239268Sgonzo	u_int clevel, csize, i, sel;
642129198Scognet	u_int multiplier;
643239268Sgonzo	u_char type;
644129198Scognet
645129198Scognet	__asm __volatile("mrc p15, 0, %0, c0, c0, 1"
646129198Scognet		: "=r" (ctype));
647129198Scognet
648295096Smmel	cpuid = cpu_ident();
649129198Scognet	/*
650129198Scognet	 * ...and thus spake the ARM ARM:
651129198Scognet	 *
652129198Scognet	 * If an <opcode2> value corresponding to an unimplemented or
653129198Scognet	 * reserved ID register is encountered, the System Control
654129198Scognet	 * processor returns the value of the main ID register.
655129198Scognet	 */
656239268Sgonzo	if (ctype == cpuid)
657129198Scognet		goto out;
658129198Scognet
659239268Sgonzo	if (CPU_CT_FORMAT(ctype) == CPU_CT_ARMV7) {
660278518Szbb		/* Resolve minimal cache line sizes */
661278518Szbb		arm_dcache_min_line_size = 1 << (CPU_CT_DMINLINE(ctype) + 2);
662278518Szbb		arm_icache_min_line_size = 1 << (CPU_CT_IMINLINE(ctype) + 2);
663278518Szbb		arm_idcache_min_line_size =
664278518Szbb		    min(arm_icache_min_line_size, arm_dcache_min_line_size);
665278518Szbb
666239268Sgonzo		__asm __volatile("mrc p15, 1, %0, c0, c0, 1"
667239268Sgonzo		    : "=r" (clevel));
668239268Sgonzo		arm_cache_level = clevel;
669239268Sgonzo		arm_cache_loc = CPU_CLIDR_LOC(arm_cache_level);
670239268Sgonzo		i = 0;
671239268Sgonzo		while ((type = (clevel & 0x7)) && i < 7) {
672239268Sgonzo			if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
673239268Sgonzo			    type == CACHE_SEP_CACHE) {
674239268Sgonzo				sel = i << 1;
675239268Sgonzo				__asm __volatile("mcr p15, 2, %0, c0, c0, 0"
676239268Sgonzo				    : : "r" (sel));
677239268Sgonzo				__asm __volatile("mrc p15, 1, %0, c0, c0, 0"
678239268Sgonzo				    : "=r" (csize));
679239268Sgonzo				arm_cache_type[sel] = csize;
680283366Sandrew				arm_dcache_align = 1 <<
681239268Sgonzo				    (CPUV7_CT_xSIZE_LEN(csize) + 4);
682239268Sgonzo				arm_dcache_align_mask = arm_dcache_align - 1;
683239268Sgonzo			}
684239268Sgonzo			if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
685239268Sgonzo				sel = (i << 1) | 1;
686239268Sgonzo				__asm __volatile("mcr p15, 2, %0, c0, c0, 0"
687239268Sgonzo				    : : "r" (sel));
688239268Sgonzo				__asm __volatile("mrc p15, 1, %0, c0, c0, 0"
689239268Sgonzo				    : "=r" (csize));
690239268Sgonzo				arm_cache_type[sel] = csize;
691239268Sgonzo			}
692239268Sgonzo			i++;
693239268Sgonzo			clevel >>= 3;
694239268Sgonzo		}
695239268Sgonzo	} else {
696239268Sgonzo		if ((ctype & CPU_CT_S) == 0)
697239268Sgonzo			arm_pcache_unified = 1;
698129198Scognet
699239268Sgonzo		/*
700239268Sgonzo		 * If you want to know how this code works, go read the ARM ARM.
701239268Sgonzo		 */
702129198Scognet
703239268Sgonzo		arm_pcache_type = CPU_CT_CTYPE(ctype);
704129198Scognet
705239268Sgonzo		if (arm_pcache_unified == 0) {
706239268Sgonzo			isize = CPU_CT_ISIZE(ctype);
707239268Sgonzo			multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2;
708239268Sgonzo			arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3);
709239268Sgonzo			if (CPU_CT_xSIZE_ASSOC(isize) == 0) {
710239268Sgonzo				if (isize & CPU_CT_xSIZE_M)
711239268Sgonzo					arm_picache_line_size = 0; /* not present */
712239268Sgonzo				else
713239268Sgonzo					arm_picache_ways = 1;
714239268Sgonzo			} else {
715239268Sgonzo				arm_picache_ways = multiplier <<
716239268Sgonzo				    (CPU_CT_xSIZE_ASSOC(isize) - 1);
717239268Sgonzo			}
718239268Sgonzo			arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
719239268Sgonzo		}
720239268Sgonzo
721239268Sgonzo		dsize = CPU_CT_DSIZE(ctype);
722239268Sgonzo		multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
723239268Sgonzo		arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
724239268Sgonzo		if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
725239268Sgonzo			if (dsize & CPU_CT_xSIZE_M)
726239268Sgonzo				arm_pdcache_line_size = 0; /* not present */
727129198Scognet			else
728239268Sgonzo				arm_pdcache_ways = 1;
729129198Scognet		} else {
730239268Sgonzo			arm_pdcache_ways = multiplier <<
731239268Sgonzo			    (CPU_CT_xSIZE_ASSOC(dsize) - 1);
732129198Scognet		}
733239268Sgonzo		arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
734129198Scognet
735239268Sgonzo		arm_dcache_align = arm_pdcache_line_size;
736129198Scognet
737239268Sgonzo		arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2;
738239268Sgonzo		arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3;
739239268Sgonzo		arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) -
740239268Sgonzo		    CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize);
741129198Scognet
742239268Sgonzo	out:
743239268Sgonzo		arm_dcache_align_mask = arm_dcache_align - 1;
744239268Sgonzo	}
745129198Scognet}
746262958Sian#endif /* ARM9 || XSCALE */
747129198Scognet
748129198Scognet/*
749129198Scognet * Cannot panic here as we may not have a console yet ...
750129198Scognet */
751129198Scognet
752129198Scognetint
753129198Scognetset_cpufuncs()
754129198Scognet{
755295096Smmel	cputype = cpu_ident();
756129198Scognet	cputype &= CPU_ID_CPU_MASK;
757129198Scognet
758129198Scognet#ifdef CPU_ARM9
759129198Scognet	if (((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD ||
760129198Scognet	     (cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_TI) &&
761129198Scognet	    (cputype & 0x0000f000) == 0x00009000) {
762129198Scognet		cpufuncs = arm9_cpufuncs;
763129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* V4 or higher */
764129198Scognet		get_cachetype_cp15();
765146605Scognet		arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize;
766146605Scognet		arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize +
767146605Scognet		    arm_dcache_l2_nsets)) - arm9_dcache_sets_inc;
768146605Scognet		arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc);
769146605Scognet		arm9_dcache_index_max = 0U - arm9_dcache_index_inc;
770137270Scognet		pmap_pte_init_generic();
771166655Scognet		goto out;
772129198Scognet	}
773129198Scognet#endif /* CPU_ARM9 */
774280809Sandrew#if defined(CPU_ARM9E)
775239268Sgonzo	if (cputype == CPU_ID_MV88FR131 || cputype == CPU_ID_MV88FR571_VD ||
776183835Sraj	    cputype == CPU_ID_MV88FR571_41) {
777239268Sgonzo		uint32_t sheeva_ctrl;
778183835Sraj
779239268Sgonzo		sheeva_ctrl = (MV_DC_STREAM_ENABLE | MV_BTB_DISABLE |
780239268Sgonzo		    MV_L2_ENABLE);
781239268Sgonzo		/*
782239268Sgonzo		 * Workaround for Marvell MV78100 CPU: Cache prefetch
783239268Sgonzo		 * mechanism may affect the cache coherency validity,
784239268Sgonzo		 * so it needs to be disabled.
785239268Sgonzo		 *
786239268Sgonzo		 * Refer to errata document MV-S501058-00C.pdf (p. 3.1
787239268Sgonzo		 * L2 Prefetching Mechanism) for details.
788239268Sgonzo		 */
789239268Sgonzo		if (cputype == CPU_ID_MV88FR571_VD ||
790239268Sgonzo		    cputype == CPU_ID_MV88FR571_41)
791239268Sgonzo			sheeva_ctrl |= MV_L2_PREFETCH_DISABLE;
792212825Smav
793239268Sgonzo		sheeva_control_ext(0xffffffff & ~MV_WA_ENABLE, sheeva_ctrl);
794183835Sraj
795239268Sgonzo		cpufuncs = sheeva_cpufuncs;
796172738Simp		get_cachetype_cp15();
797172738Simp		pmap_pte_init_generic();
798174058Scognet		goto out;
799280809Sandrew	} else if (cputype == CPU_ID_ARM926EJS) {
800239268Sgonzo		cpufuncs = armv5_ec_cpufuncs;
801239268Sgonzo		get_cachetype_cp15();
802239268Sgonzo		pmap_pte_init_generic();
803239268Sgonzo		goto out;
804172738Simp	}
805280809Sandrew#endif /* CPU_ARM9E */
806280824Sandrew#if defined(CPU_ARM1176)
807280824Sandrew	if (cputype == CPU_ID_ARM1176JZS) {
808280868Sandrew		cpufuncs = arm1176_cpufuncs;
809244480Sgonzo		cpu_reset_needs_v4_MMU_disable = 1;     /* V4 or higher */
810244480Sgonzo		get_cachetype_cp15();
811244480Sgonzo		goto out;
812244480Sgonzo	}
813280824Sandrew#endif /* CPU_ARM1176 */
814259640Sganbold#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
815256629Sbr	if (cputype == CPU_ID_CORTEXA5 ||
816256629Sbr	    cputype == CPU_ID_CORTEXA7 ||
817253857Sganbold	    cputype == CPU_ID_CORTEXA8R1 ||
818239268Sgonzo	    cputype == CPU_ID_CORTEXA8R2 ||
819239268Sgonzo	    cputype == CPU_ID_CORTEXA8R3 ||
820239268Sgonzo	    cputype == CPU_ID_CORTEXA9R1 ||
821249999Swkoszek	    cputype == CPU_ID_CORTEXA9R2 ||
822252361Sray	    cputype == CPU_ID_CORTEXA9R3 ||
823286725Smarcel	    cputype == CPU_ID_CORTEXA9R4 ||
824277156Sganbold	    cputype == CPU_ID_CORTEXA12R0 ||
825263982Sbr	    cputype == CPU_ID_CORTEXA15R0 ||
826263982Sbr	    cputype == CPU_ID_CORTEXA15R1 ||
827263982Sbr	    cputype == CPU_ID_CORTEXA15R2 ||
828263982Sbr	    cputype == CPU_ID_CORTEXA15R3 ||
829291425Smmel	    cputype == CPU_ID_KRAIT300R0 ||
830291425Smmel	    cputype == CPU_ID_KRAIT300R1 ) {
831239268Sgonzo		cpufuncs = cortexa_cpufuncs;
832239268Sgonzo		cpu_reset_needs_v4_MMU_disable = 1;     /* V4 or higher */
833239268Sgonzo		get_cachetype_cp15();
834239268Sgonzo		goto out;
835239268Sgonzo	}
836239268Sgonzo#endif /* CPU_CORTEXA */
837283366Sandrew
838239268Sgonzo#if defined(CPU_MV_PJ4B)
839257281Szbb	if (cputype == CPU_ID_MV88SV581X_V7 ||
840240486Sgber	    cputype == CPU_ID_MV88SV584X_V7 ||
841239268Sgonzo	    cputype == CPU_ID_ARM_88SV581X_V7) {
842257281Szbb		cpufuncs = pj4bv7_cpufuncs;
843239268Sgonzo		get_cachetype_cp15();
844239268Sgonzo		goto out;
845239268Sgonzo	}
846239268Sgonzo#endif /* CPU_MV_PJ4B */
847129198Scognet
848280842Sandrew#if defined(CPU_FA526)
849207611Skevlo	if (cputype == CPU_ID_FA526 || cputype == CPU_ID_FA626TE) {
850201468Srpaulo		cpufuncs = fa526_cpufuncs;
851201468Srpaulo		cpu_reset_needs_v4_MMU_disable = 1;	/* SA needs it	*/
852201468Srpaulo		get_cachetype_cp15();
853201468Srpaulo		pmap_pte_init_generic();
854201468Srpaulo
855201468Srpaulo		goto out;
856201468Srpaulo	}
857280842Sandrew#endif	/* CPU_FA526 */
858262958Sian
859161592Scognet#if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219)
860129198Scognet	if (cputype == CPU_ID_80321_400 || cputype == CPU_ID_80321_600 ||
861161592Scognet	    cputype == CPU_ID_80321_400_B0 || cputype == CPU_ID_80321_600_B0 ||
862161592Scognet	    cputype == CPU_ID_80219_400 || cputype == CPU_ID_80219_600) {
863129198Scognet		cpufuncs = xscale_cpufuncs;
864129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
865129198Scognet		get_cachetype_cp15();
866129198Scognet		pmap_pte_init_xscale();
867166655Scognet		goto out;
868129198Scognet	}
869129198Scognet#endif /* CPU_XSCALE_80321 */
870161592Scognet
871164080Scognet#if defined(CPU_XSCALE_81342)
872164080Scognet	if (cputype == CPU_ID_81342) {
873164080Scognet		cpufuncs = xscalec3_cpufuncs;
874164080Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
875164080Scognet		get_cachetype_cp15();
876164080Scognet		pmap_pte_init_xscale();
877166655Scognet		goto out;
878164080Scognet	}
879164080Scognet#endif /* CPU_XSCALE_81342 */
880129198Scognet#ifdef CPU_XSCALE_PXA2X0
881129198Scognet	/* ignore core revision to test PXA2xx CPUs */
882129198Scognet	if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA250 ||
883191817Sstas	    (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X ||
884129198Scognet	    (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA210) {
885129198Scognet
886129198Scognet		cpufuncs = xscale_cpufuncs;
887129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
888129198Scognet		get_cachetype_cp15();
889129198Scognet		pmap_pte_init_xscale();
890129198Scognet
891166655Scognet		goto out;
892129198Scognet	}
893129198Scognet#endif /* CPU_XSCALE_PXA2X0 */
894129198Scognet#ifdef CPU_XSCALE_IXP425
895129198Scognet	if (cputype == CPU_ID_IXP425_533 || cputype == CPU_ID_IXP425_400 ||
896186352Ssam            cputype == CPU_ID_IXP425_266 || cputype == CPU_ID_IXP435) {
897129198Scognet
898129198Scognet		cpufuncs = xscale_cpufuncs;
899129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
900129198Scognet		get_cachetype_cp15();
901129198Scognet		pmap_pte_init_xscale();
902129198Scognet
903166655Scognet		goto out;
904129198Scognet	}
905129198Scognet#endif /* CPU_XSCALE_IXP425 */
906129198Scognet	/*
907129198Scognet	 * Bzzzz. And the answer was ...
908129198Scognet	 */
909129198Scognet	panic("No support for this CPU type (%08x) in kernel", cputype);
910129198Scognet	return(ARCHITECTURE_NOT_PRESENT);
911166655Scognetout:
912166655Scognet	uma_set_align(arm_dcache_align_mask);
913166655Scognet	return (0);
914129198Scognet}
915129198Scognet
916129198Scognet/*
917129198Scognet * CPU Setup code
918129198Scognet */
919129198Scognet
920129198Scognet#ifdef CPU_ARM9
921129198Scognetvoid
922280823Sandrewarm9_setup(void)
923129198Scognet{
924129198Scognet	int cpuctrl, cpuctrlmask;
925129198Scognet
926129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
927129198Scognet	    | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
928129198Scognet	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
929157618Scognet	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE |
930157618Scognet	    CPU_CONTROL_ROUNDROBIN;
931129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
932129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
933129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
934129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
935129198Scognet		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
936146605Scognet		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_VECRELOC
937146605Scognet		 | CPU_CONTROL_ROUNDROBIN;
938129198Scognet
939129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
940129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
941129198Scognet#endif
942129198Scognet
943129198Scognet#ifdef __ARMEB__
944129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
945129198Scognet#endif
946142050Scognet	if (vector_page == ARM_VECTORS_HIGH)
947142050Scognet		cpuctrl |= CPU_CONTROL_VECRELOC;
948129198Scognet
949129198Scognet	/* Clear out the cache */
950129198Scognet	cpu_idcache_wbinv_all();
951129198Scognet
952129198Scognet	/* Set the control register */
953146605Scognet	cpu_control(cpuctrlmask, cpuctrl);
954129198Scognet	ctrl = cpuctrl;
955129198Scognet
956129198Scognet}
957129198Scognet#endif	/* CPU_ARM9 */
958129198Scognet
959280809Sandrew#if defined(CPU_ARM9E)
960129198Scognetvoid
961280823Sandrewarm10_setup(void)
962129198Scognet{
963129198Scognet	int cpuctrl, cpuctrlmask;
964129198Scognet
965129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
966236991Simp	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
967129198Scognet	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE;
968129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
969129198Scognet	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
970129198Scognet	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
971129198Scognet	    | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
972129198Scognet	    | CPU_CONTROL_BPRD_ENABLE
973129198Scognet	    | CPU_CONTROL_ROUNDROBIN | CPU_CONTROL_CPCLK;
974129198Scognet
975129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
976129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
977129198Scognet#endif
978129198Scognet
979129198Scognet#ifdef __ARMEB__
980129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
981129198Scognet#endif
982129198Scognet
983129198Scognet	/* Clear out the cache */
984129198Scognet	cpu_idcache_wbinv_all();
985129198Scognet
986129198Scognet	/* Now really make sure they are clean.  */
987172738Simp	__asm __volatile ("mcr\tp15, 0, r0, c7, c7, 0" : : );
988129198Scognet
989174058Scognet	if (vector_page == ARM_VECTORS_HIGH)
990174058Scognet		cpuctrl |= CPU_CONTROL_VECRELOC;
991174058Scognet
992129198Scognet	/* Set the control register */
993129198Scognet	ctrl = cpuctrl;
994129198Scognet	cpu_control(0xffffffff, cpuctrl);
995129198Scognet
996129198Scognet	/* And again. */
997129198Scognet	cpu_idcache_wbinv_all();
998129198Scognet}
999172738Simp#endif	/* CPU_ARM9E || CPU_ARM10 */
1000129198Scognet
1001280824Sandrew#if defined(CPU_ARM1176) \
1002266083Smarkm || defined(CPU_MV_PJ4B) \
1003266083Smarkm || defined(CPU_CORTEXA) || defined(CPU_KRAIT)
1004266083Smarkmstatic __inline void
1005266083Smarkmcpu_scc_setup_ccnt(void)
1006266083Smarkm{
1007266083Smarkm/* This is how you give userland access to the CCNT and PMCn
1008266083Smarkm * registers.
1009266083Smarkm * BEWARE! This gives write access also, which may not be what
1010266083Smarkm * you want!
1011266083Smarkm */
1012266083Smarkm#ifdef _PMC_USER_READ_WRITE_
1013266083Smarkm	/* Set PMUSERENR[0] to allow userland access */
1014283365Sandrew	cp15_pmuserenr_set(1);
1015266083Smarkm#endif
1016280824Sandrew#if defined(CPU_ARM1176)
1017267597Stuexen	/* Set PMCR[2,0] to enable counters and reset CCNT */
1018283365Sandrew	cp15_pmcr_set(5);
1019267597Stuexen#else
1020267597Stuexen	/* Set up the PMCCNTR register as a cyclecounter:
1021266083Smarkm	 * Set PMINTENCLR to 0xFFFFFFFF to block interrupts
1022266083Smarkm	 * Set PMCR[2,0] to enable counters and reset CCNT
1023266083Smarkm	 * Set PMCNTENSET to 0x80000000 to enable CCNT */
1024283365Sandrew	cp15_pminten_clr(0xFFFFFFFF);
1025283365Sandrew	cp15_pmcr_set(5);
1026283365Sandrew	cp15_pmcnten_set(0x80000000);
1027267597Stuexen#endif
1028266083Smarkm}
1029266083Smarkm#endif
1030266083Smarkm
1031280824Sandrew#if defined(CPU_ARM1176)
1032172738Simpvoid
1033280823Sandrewarm11x6_setup(void)
1034172738Simp{
1035244480Sgonzo	int cpuctrl, cpuctrl_wax;
1036244480Sgonzo	uint32_t auxctrl, auxctrl_wax;
1037244480Sgonzo	uint32_t tmp, tmp2;
1038244480Sgonzo	uint32_t sbz=0;
1039244480Sgonzo	uint32_t cpuid;
1040172738Simp
1041295096Smmel	cpuid = cpu_ident();
1042244480Sgonzo
1043244480Sgonzo	cpuctrl =
1044244480Sgonzo		CPU_CONTROL_MMU_ENABLE  |
1045244480Sgonzo		CPU_CONTROL_DC_ENABLE   |
1046244480Sgonzo		CPU_CONTROL_WBUF_ENABLE |
1047244480Sgonzo		CPU_CONTROL_32BP_ENABLE |
1048244480Sgonzo		CPU_CONTROL_32BD_ENABLE |
1049244480Sgonzo		CPU_CONTROL_LABT_ENABLE |
1050244480Sgonzo		CPU_CONTROL_SYST_ENABLE |
1051282019Sandrew		CPU_CONTROL_IC_ENABLE   |
1052282019Sandrew		CPU_CONTROL_UNAL_ENABLE;
1053244480Sgonzo
1054244480Sgonzo	/*
1055244480Sgonzo	 * "write as existing" bits
1056244480Sgonzo	 * inverse of this is mask
1057244480Sgonzo	 */
1058244480Sgonzo	cpuctrl_wax =
1059244480Sgonzo		(3 << 30) | /* SBZ */
1060244480Sgonzo		(1 << 29) | /* FA */
1061244480Sgonzo		(1 << 28) | /* TR */
1062283366Sandrew		(3 << 26) | /* SBZ */
1063244480Sgonzo		(3 << 19) | /* SBZ */
1064244480Sgonzo		(1 << 17);  /* SBZ */
1065244480Sgonzo
1066244480Sgonzo	cpuctrl |= CPU_CONTROL_BPRD_ENABLE;
1067244480Sgonzo	cpuctrl |= CPU_CONTROL_V6_EXTPAGE;
1068244480Sgonzo
1069172738Simp#ifdef __ARMEB__
1070172738Simp	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1071172738Simp#endif
1072244480Sgonzo
1073239701Sgonzo	if (vector_page == ARM_VECTORS_HIGH)
1074239701Sgonzo		cpuctrl |= CPU_CONTROL_VECRELOC;
1075172738Simp
1076244480Sgonzo	auxctrl = 0;
1077244480Sgonzo	auxctrl_wax = ~0;
1078244480Sgonzo
1079244480Sgonzo	/*
1080244480Sgonzo	 * Enable an errata workaround
1081244480Sgonzo	 */
1082244480Sgonzo	if ((cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM1176JZS) { /* ARM1176JZSr0 */
1083244480Sgonzo		auxctrl = ARM1176_AUXCTL_PHD;
1084244480Sgonzo		auxctrl_wax = ~ARM1176_AUXCTL_PHD;
1085244480Sgonzo	}
1086244480Sgonzo
1087244480Sgonzo	/* Clear out the cache */
1088172738Simp	cpu_idcache_wbinv_all();
1089172738Simp
1090244480Sgonzo	/* Now really make sure they are clean.  */
1091244480Sgonzo	__asm volatile ("mcr\tp15, 0, %0, c7, c7, 0" : : "r"(sbz));
1092244480Sgonzo
1093244480Sgonzo	/* Allow detection code to find the VFP if it's fitted.  */
1094283365Sandrew	cp15_cpacr_set(0x0fffffff);
1095244480Sgonzo
1096172738Simp	/* Set the control register */
1097239701Sgonzo	ctrl = cpuctrl;
1098244480Sgonzo	cpu_control(~cpuctrl_wax, cpuctrl);
1099172738Simp
1100283365Sandrew	tmp = cp15_actlr_get();
1101283365Sandrew	tmp2 = tmp;
1102283365Sandrew	tmp &= auxctrl_wax;
1103283365Sandrew	tmp |= auxctrl;
1104283365Sandrew	if (tmp != tmp2)
1105283365Sandrew		cp15_actlr_set(tmp);
1106244480Sgonzo
1107244480Sgonzo	/* And again. */
1108172738Simp	cpu_idcache_wbinv_all();
1109266083Smarkm
1110266083Smarkm	cpu_scc_setup_ccnt();
1111172738Simp}
1112280824Sandrew#endif  /* CPU_ARM1176 */
1113172738Simp
1114239268Sgonzo#ifdef CPU_MV_PJ4B
1115239268Sgonzovoid
1116280823Sandrewpj4bv7_setup(void)
1117239268Sgonzo{
1118239268Sgonzo	int cpuctrl;
1119239268Sgonzo
1120239268Sgonzo	pj4b_config();
1121239268Sgonzo
1122239268Sgonzo	cpuctrl = CPU_CONTROL_MMU_ENABLE;
1123239268Sgonzo#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1124239268Sgonzo	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1125239268Sgonzo#endif
1126239268Sgonzo	cpuctrl |= CPU_CONTROL_DC_ENABLE;
1127239268Sgonzo	cpuctrl |= (0xf << 3);
1128239268Sgonzo	cpuctrl |= CPU_CONTROL_BPRD_ENABLE;
1129239268Sgonzo	cpuctrl |= CPU_CONTROL_IC_ENABLE;
1130239268Sgonzo	if (vector_page == ARM_VECTORS_HIGH)
1131239268Sgonzo		cpuctrl |= CPU_CONTROL_VECRELOC;
1132239268Sgonzo	cpuctrl |= (0x5 << 16) | (1 < 22);
1133239268Sgonzo	cpuctrl |= CPU_CONTROL_V6_EXTPAGE;
1134239268Sgonzo
1135239268Sgonzo	/* Clear out the cache */
1136239268Sgonzo	cpu_idcache_wbinv_all();
1137239268Sgonzo
1138239268Sgonzo	/* Set the control register */
1139239268Sgonzo	ctrl = cpuctrl;
1140239268Sgonzo	cpu_control(0xFFFFFFFF, cpuctrl);
1141239268Sgonzo
1142239268Sgonzo	/* And again. */
1143239268Sgonzo	cpu_idcache_wbinv_all();
1144266083Smarkm
1145266083Smarkm	cpu_scc_setup_ccnt();
1146239268Sgonzo}
1147239268Sgonzo#endif /* CPU_MV_PJ4B */
1148239268Sgonzo
1149259640Sganbold#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
1150239268Sgonzo
1151239268Sgonzovoid
1152280823Sandrewcortexa_setup(void)
1153239268Sgonzo{
1154239268Sgonzo	int cpuctrl, cpuctrlmask;
1155283366Sandrew
1156239268Sgonzo	cpuctrlmask = CPU_CONTROL_MMU_ENABLE |     /* MMU enable         [0] */
1157239268Sgonzo	    CPU_CONTROL_AFLT_ENABLE |    /* Alignment fault    [1] */
1158239268Sgonzo	    CPU_CONTROL_DC_ENABLE |      /* DCache enable      [2] */
1159239268Sgonzo	    CPU_CONTROL_BPRD_ENABLE |    /* Branch prediction [11] */
1160239268Sgonzo	    CPU_CONTROL_IC_ENABLE |      /* ICache enable     [12] */
1161239268Sgonzo	    CPU_CONTROL_VECRELOC;        /* Vector relocation [13] */
1162283366Sandrew
1163239268Sgonzo	cpuctrl = CPU_CONTROL_MMU_ENABLE |
1164239268Sgonzo	    CPU_CONTROL_IC_ENABLE |
1165239268Sgonzo	    CPU_CONTROL_DC_ENABLE |
1166239268Sgonzo	    CPU_CONTROL_BPRD_ENABLE;
1167283366Sandrew
1168239268Sgonzo#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1169239268Sgonzo	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1170239268Sgonzo#endif
1171283366Sandrew
1172239268Sgonzo	/* Switch to big endian */
1173239268Sgonzo#ifdef __ARMEB__
1174239268Sgonzo	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1175239268Sgonzo#endif
1176283366Sandrew
1177239268Sgonzo	/* Check if the vector page is at the high address (0xffff0000) */
1178239268Sgonzo	if (vector_page == ARM_VECTORS_HIGH)
1179239268Sgonzo		cpuctrl |= CPU_CONTROL_VECRELOC;
1180283366Sandrew
1181239268Sgonzo	/* Clear out the cache */
1182239268Sgonzo	cpu_idcache_wbinv_all();
1183283366Sandrew
1184239268Sgonzo	/* Set the control register */
1185239268Sgonzo	ctrl = cpuctrl;
1186239268Sgonzo	cpu_control(cpuctrlmask, cpuctrl);
1187283366Sandrew
1188239268Sgonzo	/* And again. */
1189239268Sgonzo	cpu_idcache_wbinv_all();
1190289602Sian#if defined(SMP) && !defined(ARM_NEW_PMAP)
1191239268Sgonzo	armv7_auxctrl((1 << 6) | (1 << 0), (1 << 6) | (1 << 0)); /* Enable SMP + TLB broadcasting  */
1192239268Sgonzo#endif
1193266083Smarkm
1194266083Smarkm	cpu_scc_setup_ccnt();
1195239268Sgonzo}
1196239268Sgonzo#endif  /* CPU_CORTEXA */
1197239268Sgonzo
1198280842Sandrew#if defined(CPU_FA526)
1199201468Srpaulovoid
1200280823Sandrewfa526_setup(void)
1201201468Srpaulo{
1202201468Srpaulo	int cpuctrl, cpuctrlmask;
1203201468Srpaulo
1204201468Srpaulo	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1205201468Srpaulo		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1206201468Srpaulo		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1207204122Skevlo		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
1208204122Skevlo		| CPU_CONTROL_BPRD_ENABLE;
1209201468Srpaulo	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1210201468Srpaulo		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1211201468Srpaulo		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1212201468Srpaulo		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
1213201468Srpaulo		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
1214201468Srpaulo		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
1215201468Srpaulo		 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC;
1216201468Srpaulo
1217201468Srpaulo#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1218201468Srpaulo	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1219201468Srpaulo#endif
1220201468Srpaulo
1221201468Srpaulo#ifdef __ARMEB__
1222201468Srpaulo	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1223201468Srpaulo#endif
1224201468Srpaulo
1225201468Srpaulo	if (vector_page == ARM_VECTORS_HIGH)
1226201468Srpaulo		cpuctrl |= CPU_CONTROL_VECRELOC;
1227201468Srpaulo
1228201468Srpaulo	/* Clear out the cache */
1229201468Srpaulo	cpu_idcache_wbinv_all();
1230201468Srpaulo
1231201468Srpaulo	/* Set the control register */
1232201468Srpaulo	ctrl = cpuctrl;
1233201468Srpaulo	cpu_control(0xffffffff, cpuctrl);
1234201468Srpaulo}
1235280842Sandrew#endif	/* CPU_FA526 */
1236201468Srpaulo
1237280847Sandrew#if defined(CPU_XSCALE_80321) || \
1238161592Scognet  defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
1239164080Scognet  defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)
1240129198Scognetvoid
1241280823Sandrewxscale_setup(void)
1242129198Scognet{
1243129198Scognet	uint32_t auxctl;
1244129198Scognet	int cpuctrl, cpuctrlmask;
1245129198Scognet
1246129198Scognet	/*
1247129198Scognet	 * The XScale Write Buffer is always enabled.  Our option
1248129198Scognet	 * is to enable/disable coalescing.  Note that bits 6:3
1249129198Scognet	 * must always be enabled.
1250129198Scognet	 */
1251129198Scognet
1252129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1253129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1254129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1255129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
1256129198Scognet		 | CPU_CONTROL_BPRD_ENABLE;
1257129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1258129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1259129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1260129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
1261129198Scognet		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
1262129198Scognet		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
1263171618Scognet		 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC | \
1264171618Scognet		 CPU_CONTROL_L2_ENABLE;
1265129198Scognet
1266129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1267129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1268129198Scognet#endif
1269129198Scognet
1270129198Scognet#ifdef __ARMEB__
1271129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1272129198Scognet#endif
1273129198Scognet
1274129198Scognet	if (vector_page == ARM_VECTORS_HIGH)
1275129198Scognet		cpuctrl |= CPU_CONTROL_VECRELOC;
1276171618Scognet#ifdef CPU_XSCALE_CORE3
1277171618Scognet	cpuctrl |= CPU_CONTROL_L2_ENABLE;
1278171618Scognet#endif
1279129198Scognet
1280129198Scognet	/* Clear out the cache */
1281129198Scognet	cpu_idcache_wbinv_all();
1282129198Scognet
1283129198Scognet	/*
1284129198Scognet	 * Set the control register.  Note that bits 6:3 must always
1285129198Scognet	 * be set to 1.
1286129198Scognet	 */
1287129198Scognet	ctrl = cpuctrl;
1288129198Scognet/*	cpu_control(cpuctrlmask, cpuctrl);*/
1289129198Scognet	cpu_control(0xffffffff, cpuctrl);
1290129198Scognet
1291129198Scognet	/* Make sure write coalescing is turned on */
1292129198Scognet	__asm __volatile("mrc p15, 0, %0, c1, c0, 1"
1293129198Scognet		: "=r" (auxctl));
1294129198Scognet#ifdef XSCALE_NO_COALESCE_WRITES
1295129198Scognet	auxctl |= XSCALE_AUXCTL_K;
1296129198Scognet#else
1297129198Scognet	auxctl &= ~XSCALE_AUXCTL_K;
1298129198Scognet#endif
1299171618Scognet#ifdef CPU_XSCALE_CORE3
1300171618Scognet	auxctl |= XSCALE_AUXCTL_LLR;
1301171618Scognet	auxctl |= XSCALE_AUXCTL_MD_MASK;
1302171618Scognet#endif
1303129198Scognet	__asm __volatile("mcr p15, 0, %0, c1, c0, 1"
1304129198Scognet		: : "r" (auxctl));
1305129198Scognet}
1306280847Sandrew#endif	/* CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425
1307161592Scognet	   CPU_XSCALE_80219 */
1308