cpufunc.c revision 283366
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 283366 2015-05-24 12:20:11Z andrew $");
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_id,			/* id			*/
109129198Scognet	cpufunc_nullop,			/* cpwait		*/
110129198Scognet
111129198Scognet	/* MMU functions */
112129198Scognet
113129198Scognet	cpufunc_control,		/* control		*/
114129198Scognet	cpufunc_domains,		/* Domain		*/
115129198Scognet	arm9_setttb,			/* Setttb		*/
116129198Scognet	cpufunc_faultstatus,		/* Faultstatus		*/
117129198Scognet	cpufunc_faultaddress,		/* Faultaddress		*/
118129198Scognet
119129198Scognet	/* TLB functions */
120129198Scognet
121129198Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
122129198Scognet	arm9_tlb_flushID_SE,		/* tlb_flushID_SE	*/
123129198Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
124129198Scognet	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
125129198Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
126129198Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
127129198Scognet
128129198Scognet	/* Cache operations */
129129198Scognet
130146605Scognet	arm9_icache_sync_all,		/* icache_sync_all	*/
131146605Scognet	arm9_icache_sync_range,		/* icache_sync_range	*/
132129198Scognet
133146605Scognet	arm9_dcache_wbinv_all,		/* dcache_wbinv_all	*/
134146605Scognet	arm9_dcache_wbinv_range,	/* dcache_wbinv_range	*/
135195798Sraj	arm9_dcache_inv_range,		/* dcache_inv_range	*/
136146605Scognet	arm9_dcache_wb_range,		/* dcache_wb_range	*/
137129198Scognet
138262420Sian	armv4_idcache_inv_all,		/* idcache_inv_all	*/
139146605Scognet	arm9_idcache_wbinv_all,		/* idcache_wbinv_all	*/
140146605Scognet	arm9_idcache_wbinv_range,	/* idcache_wbinv_range	*/
141171618Scognet	cpufunc_nullop,			/* l2cache_wbinv_all	*/
142171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
143171781Scognet	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
144171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
145265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
146129198Scognet
147129198Scognet	/* Other functions */
148129198Scognet
149129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
150129198Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
151129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
152129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
153129198Scognet
154129198Scognet	(void *)cpufunc_nullop,		/* sleep		*/
155129198Scognet
156129198Scognet	/* Soft functions */
157129198Scognet
158129198Scognet	cpufunc_null_fixup,		/* dataabt_fixup	*/
159129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
160129198Scognet
161129198Scognet	arm9_context_switch,		/* context_switch	*/
162129198Scognet
163129198Scognet	arm9_setup			/* cpu setup		*/
164129198Scognet
165129198Scognet};
166129198Scognet#endif /* CPU_ARM9 */
167129198Scognet
168280809Sandrew#if defined(CPU_ARM9E)
169172738Simpstruct cpu_functions armv5_ec_cpufuncs = {
170172738Simp	/* CPU functions */
171172738Simp
172172738Simp	cpufunc_id,			/* id			*/
173172738Simp	cpufunc_nullop,			/* cpwait		*/
174172738Simp
175172738Simp	/* MMU functions */
176172738Simp
177172738Simp	cpufunc_control,		/* control		*/
178172738Simp	cpufunc_domains,		/* Domain		*/
179172738Simp	armv5_ec_setttb,		/* Setttb		*/
180172738Simp	cpufunc_faultstatus,		/* Faultstatus		*/
181172738Simp	cpufunc_faultaddress,		/* Faultaddress		*/
182172738Simp
183172738Simp	/* TLB functions */
184172738Simp
185172738Simp	armv4_tlb_flushID,		/* tlb_flushID		*/
186172738Simp	arm10_tlb_flushID_SE,		/* tlb_flushID_SE	*/
187172738Simp	armv4_tlb_flushI,		/* tlb_flushI		*/
188172738Simp	arm10_tlb_flushI_SE,		/* tlb_flushI_SE	*/
189172738Simp	armv4_tlb_flushD,		/* tlb_flushD		*/
190172738Simp	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
191172738Simp
192172738Simp	/* Cache operations */
193172738Simp
194172738Simp	armv5_ec_icache_sync_all,	/* icache_sync_all	*/
195172738Simp	armv5_ec_icache_sync_range,	/* icache_sync_range	*/
196172738Simp
197172738Simp	armv5_ec_dcache_wbinv_all,	/* dcache_wbinv_all	*/
198172738Simp	armv5_ec_dcache_wbinv_range,	/* dcache_wbinv_range	*/
199195798Sraj	armv5_ec_dcache_inv_range,	/* dcache_inv_range	*/
200172738Simp	armv5_ec_dcache_wb_range,	/* dcache_wb_range	*/
201172738Simp
202262420Sian	armv4_idcache_inv_all,		/* idcache_inv_all	*/
203172738Simp	armv5_ec_idcache_wbinv_all,	/* idcache_wbinv_all	*/
204172738Simp	armv5_ec_idcache_wbinv_range,	/* idcache_wbinv_range	*/
205172738Simp
206173442Scognet	cpufunc_nullop,                 /* l2cache_wbinv_all    */
207173442Scognet	(void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
208173442Scognet      	(void *)cpufunc_nullop,         /* l2cache_inv_range    */
209173442Scognet	(void *)cpufunc_nullop,         /* l2cache_wb_range     */
210265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
211236991Simp
212172738Simp	/* Other functions */
213172738Simp
214172738Simp	cpufunc_nullop,			/* flush_prefetchbuf	*/
215172738Simp	armv4_drain_writebuf,		/* drain_writebuf	*/
216172738Simp	cpufunc_nullop,			/* flush_brnchtgt_C	*/
217172738Simp	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
218172738Simp
219172738Simp	(void *)cpufunc_nullop,		/* sleep		*/
220172738Simp
221172738Simp	/* Soft functions */
222172738Simp
223172738Simp	cpufunc_null_fixup,		/* dataabt_fixup	*/
224172738Simp	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
225172738Simp
226172738Simp	arm10_context_switch,		/* context_switch	*/
227172738Simp
228172738Simp	arm10_setup			/* cpu setup		*/
229172738Simp
230172738Simp};
231183835Sraj
232186933Srajstruct cpu_functions sheeva_cpufuncs = {
233183835Sraj	/* CPU functions */
234183835Sraj
235183835Sraj	cpufunc_id,			/* id			*/
236183835Sraj	cpufunc_nullop,			/* cpwait		*/
237183835Sraj
238183835Sraj	/* MMU functions */
239183835Sraj
240183835Sraj	cpufunc_control,		/* control		*/
241183835Sraj	cpufunc_domains,		/* Domain		*/
242186933Sraj	sheeva_setttb,			/* Setttb		*/
243183835Sraj	cpufunc_faultstatus,		/* Faultstatus		*/
244183835Sraj	cpufunc_faultaddress,		/* Faultaddress		*/
245183835Sraj
246183835Sraj	/* TLB functions */
247183835Sraj
248183835Sraj	armv4_tlb_flushID,		/* tlb_flushID		*/
249183835Sraj	arm10_tlb_flushID_SE,		/* tlb_flushID_SE	*/
250183835Sraj	armv4_tlb_flushI,		/* tlb_flushI		*/
251183835Sraj	arm10_tlb_flushI_SE,		/* tlb_flushI_SE	*/
252183835Sraj	armv4_tlb_flushD,		/* tlb_flushD		*/
253183835Sraj	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
254183835Sraj
255183835Sraj	/* Cache operations */
256183835Sraj
257183835Sraj	armv5_ec_icache_sync_all,	/* icache_sync_all	*/
258183835Sraj	armv5_ec_icache_sync_range,	/* icache_sync_range	*/
259183835Sraj
260183835Sraj	armv5_ec_dcache_wbinv_all,	/* dcache_wbinv_all	*/
261186933Sraj	sheeva_dcache_wbinv_range,	/* dcache_wbinv_range	*/
262186933Sraj	sheeva_dcache_inv_range,	/* dcache_inv_range	*/
263186933Sraj	sheeva_dcache_wb_range,		/* dcache_wb_range	*/
264183835Sraj
265262420Sian	armv4_idcache_inv_all,		/* idcache_inv_all	*/
266183835Sraj	armv5_ec_idcache_wbinv_all,	/* idcache_wbinv_all	*/
267186933Sraj	sheeva_idcache_wbinv_range,	/* idcache_wbinv_all	*/
268183835Sraj
269186933Sraj	sheeva_l2cache_wbinv_all,	/* l2cache_wbinv_all    */
270186933Sraj	sheeva_l2cache_wbinv_range,	/* l2cache_wbinv_range  */
271186933Sraj	sheeva_l2cache_inv_range,	/* l2cache_inv_range    */
272186933Sraj	sheeva_l2cache_wb_range,	/* l2cache_wb_range     */
273265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
274183835Sraj
275183835Sraj	/* Other functions */
276183835Sraj
277183835Sraj	cpufunc_nullop,			/* flush_prefetchbuf	*/
278183835Sraj	armv4_drain_writebuf,		/* drain_writebuf	*/
279183835Sraj	cpufunc_nullop,			/* flush_brnchtgt_C	*/
280183835Sraj	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
281183835Sraj
282212825Smav	sheeva_cpu_sleep,		/* sleep		*/
283183835Sraj
284183835Sraj	/* Soft functions */
285183835Sraj
286183835Sraj	cpufunc_null_fixup,		/* dataabt_fixup	*/
287183835Sraj	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
288183835Sraj
289183835Sraj	arm10_context_switch,		/* context_switch	*/
290183835Sraj
291183835Sraj	arm10_setup			/* cpu setup		*/
292183835Sraj};
293280809Sandrew#endif /* CPU_ARM9E */
294172738Simp
295239268Sgonzo#ifdef CPU_MV_PJ4B
296239268Sgonzostruct cpu_functions pj4bv7_cpufuncs = {
297239268Sgonzo	/* CPU functions */
298239268Sgonzo
299239268Sgonzo	cpufunc_id,			/* id			*/
300266672Szbb	armv7_drain_writebuf,		/* cpwait		*/
301239268Sgonzo
302239268Sgonzo	/* MMU functions */
303239268Sgonzo
304239268Sgonzo	cpufunc_control,		/* control		*/
305239268Sgonzo	cpufunc_domains,		/* Domain		*/
306266672Szbb	armv7_setttb,			/* Setttb		*/
307239268Sgonzo	cpufunc_faultstatus,		/* Faultstatus		*/
308239268Sgonzo	cpufunc_faultaddress,		/* Faultaddress		*/
309239268Sgonzo
310239268Sgonzo	/* TLB functions */
311239268Sgonzo
312239268Sgonzo	armv7_tlb_flushID,		/* tlb_flushID		*/
313239268Sgonzo	armv7_tlb_flushID_SE,		/* tlb_flushID_SE	*/
314239268Sgonzo	armv7_tlb_flushID,		/* tlb_flushI		*/
315239268Sgonzo	armv7_tlb_flushID_SE,		/* tlb_flushI_SE	*/
316239268Sgonzo	armv7_tlb_flushID,		/* tlb_flushD		*/
317239268Sgonzo	armv7_tlb_flushID_SE,		/* tlb_flushD_SE	*/
318239268Sgonzo
319239268Sgonzo	/* Cache operations */
320239268Sgonzo	armv7_idcache_wbinv_all,	/* icache_sync_all	*/
321239268Sgonzo	armv7_icache_sync_range,	/* icache_sync_range	*/
322239268Sgonzo
323239268Sgonzo	armv7_dcache_wbinv_all,		/* dcache_wbinv_all	*/
324239268Sgonzo	armv7_dcache_wbinv_range,	/* dcache_wbinv_range	*/
325239268Sgonzo	armv7_dcache_inv_range,		/* dcache_inv_range	*/
326239268Sgonzo	armv7_dcache_wb_range,		/* dcache_wb_range	*/
327239268Sgonzo
328262420Sian	armv7_idcache_inv_all,		/* idcache_inv_all	*/
329239268Sgonzo	armv7_idcache_wbinv_all,	/* idcache_wbinv_all	*/
330239268Sgonzo	armv7_idcache_wbinv_range,	/* idcache_wbinv_all	*/
331239268Sgonzo
332239268Sgonzo	(void *)cpufunc_nullop,		/* l2cache_wbinv_all	*/
333239268Sgonzo	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
334239268Sgonzo	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
335239268Sgonzo	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
336265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
337239268Sgonzo
338239268Sgonzo	/* Other functions */
339239268Sgonzo
340266672Szbb	cpufunc_nullop,			/* flush_prefetchbuf	*/
341266672Szbb	armv7_drain_writebuf,		/* drain_writebuf	*/
342266672Szbb	cpufunc_nullop,			/* flush_brnchtgt_C	*/
343266672Szbb	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
344239268Sgonzo
345239268Sgonzo	(void *)cpufunc_nullop,		/* sleep		*/
346239268Sgonzo
347239268Sgonzo	/* Soft functions */
348239268Sgonzo
349239268Sgonzo	cpufunc_null_fixup,		/* dataabt_fixup	*/
350239268Sgonzo	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
351239268Sgonzo
352266672Szbb	armv7_context_switch,		/* context_switch	*/
353239268Sgonzo
354239268Sgonzo	pj4bv7_setup			/* cpu setup		*/
355239268Sgonzo};
356239268Sgonzo#endif /* CPU_MV_PJ4B */
357239268Sgonzo
358280847Sandrew#if defined(CPU_XSCALE_80321) || \
359161592Scognet  defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
360161592Scognet  defined(CPU_XSCALE_80219)
361161592Scognet
362129198Scognetstruct cpu_functions xscale_cpufuncs = {
363129198Scognet	/* CPU functions */
364283366Sandrew
365129198Scognet	cpufunc_id,			/* id			*/
366129198Scognet	xscale_cpwait,			/* cpwait		*/
367129198Scognet
368129198Scognet	/* MMU functions */
369129198Scognet
370129198Scognet	xscale_control,			/* control		*/
371129198Scognet	cpufunc_domains,		/* domain		*/
372129198Scognet	xscale_setttb,			/* setttb		*/
373129198Scognet	cpufunc_faultstatus,		/* faultstatus		*/
374129198Scognet	cpufunc_faultaddress,		/* faultaddress		*/
375129198Scognet
376129198Scognet	/* TLB functions */
377129198Scognet
378129198Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
379129198Scognet	xscale_tlb_flushID_SE,		/* tlb_flushID_SE	*/
380129198Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
381129198Scognet	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
382129198Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
383129198Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
384129198Scognet
385129198Scognet	/* Cache operations */
386129198Scognet
387129198Scognet	xscale_cache_syncI,		/* icache_sync_all	*/
388129198Scognet	xscale_cache_syncI_rng,		/* icache_sync_range	*/
389129198Scognet
390129198Scognet	xscale_cache_purgeD,		/* dcache_wbinv_all	*/
391129198Scognet	xscale_cache_purgeD_rng,	/* dcache_wbinv_range	*/
392129198Scognet	xscale_cache_flushD_rng,	/* dcache_inv_range	*/
393129198Scognet	xscale_cache_cleanD_rng,	/* dcache_wb_range	*/
394129198Scognet
395262420Sian	xscale_cache_flushID,		/* idcache_inv_all	*/
396129198Scognet	xscale_cache_purgeID,		/* idcache_wbinv_all	*/
397129198Scognet	xscale_cache_purgeID_rng,	/* idcache_wbinv_range	*/
398171618Scognet	cpufunc_nullop,			/* l2cache_wbinv_all 	*/
399171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
400171781Scognet	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
401171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
402265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
403129198Scognet
404129198Scognet	/* Other functions */
405129198Scognet
406129198Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
407129198Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
408129198Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
409129198Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
410129198Scognet
411129198Scognet	xscale_cpu_sleep,		/* sleep		*/
412129198Scognet
413129198Scognet	/* Soft functions */
414129198Scognet
415129198Scognet	cpufunc_null_fixup,		/* dataabt_fixup	*/
416129198Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
417129198Scognet
418129198Scognet	xscale_context_switch,		/* context_switch	*/
419129198Scognet
420129198Scognet	xscale_setup			/* cpu setup		*/
421129198Scognet};
422129198Scognet#endif
423280847Sandrew/* CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425
424161592Scognet   CPU_XSCALE_80219 */
425129198Scognet
426164080Scognet#ifdef CPU_XSCALE_81342
427164080Scognetstruct cpu_functions xscalec3_cpufuncs = {
428164080Scognet	/* CPU functions */
429283366Sandrew
430164080Scognet	cpufunc_id,			/* id			*/
431164080Scognet	xscale_cpwait,			/* cpwait		*/
432164080Scognet
433164080Scognet	/* MMU functions */
434164080Scognet
435164080Scognet	xscale_control,			/* control		*/
436164080Scognet	cpufunc_domains,		/* domain		*/
437164080Scognet	xscalec3_setttb,		/* setttb		*/
438164080Scognet	cpufunc_faultstatus,		/* faultstatus		*/
439164080Scognet	cpufunc_faultaddress,		/* faultaddress		*/
440164080Scognet
441164080Scognet	/* TLB functions */
442164080Scognet
443164080Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
444164080Scognet	xscale_tlb_flushID_SE,		/* tlb_flushID_SE	*/
445164080Scognet	armv4_tlb_flushI,		/* tlb_flushI		*/
446164080Scognet	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
447164080Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
448164080Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
449164080Scognet
450164080Scognet	/* Cache operations */
451164080Scognet
452164080Scognet	xscalec3_cache_syncI,		/* icache_sync_all	*/
453171618Scognet	xscalec3_cache_syncI_rng,	/* icache_sync_range	*/
454164080Scognet
455164080Scognet	xscalec3_cache_purgeD,		/* dcache_wbinv_all	*/
456164080Scognet	xscalec3_cache_purgeD_rng,	/* dcache_wbinv_range	*/
457164080Scognet	xscale_cache_flushD_rng,	/* dcache_inv_range	*/
458164080Scognet	xscalec3_cache_cleanD_rng,	/* dcache_wb_range	*/
459164080Scognet
460262420Sian	xscale_cache_flushID,		/* idcache_inv_all	*/
461171618Scognet	xscalec3_cache_purgeID,		/* idcache_wbinv_all	*/
462164080Scognet	xscalec3_cache_purgeID_rng,	/* idcache_wbinv_range	*/
463171618Scognet	xscalec3_l2cache_purge,		/* l2cache_wbinv_all	*/
464171618Scognet	xscalec3_l2cache_purge_rng,	/* l2cache_wbinv_range	*/
465171618Scognet	xscalec3_l2cache_flush_rng,	/* l2cache_inv_range	*/
466171618Scognet	xscalec3_l2cache_clean_rng,	/* l2cache_wb_range	*/
467265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
468164080Scognet
469164080Scognet	/* Other functions */
470164080Scognet
471164080Scognet	cpufunc_nullop,			/* flush_prefetchbuf	*/
472164080Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
473164080Scognet	cpufunc_nullop,			/* flush_brnchtgt_C	*/
474164080Scognet	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
475164080Scognet
476164080Scognet	xscale_cpu_sleep,		/* sleep		*/
477164080Scognet
478164080Scognet	/* Soft functions */
479164080Scognet
480164080Scognet	cpufunc_null_fixup,		/* dataabt_fixup	*/
481164080Scognet	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
482164080Scognet
483164080Scognet	xscalec3_context_switch,	/* context_switch	*/
484164080Scognet
485164080Scognet	xscale_setup			/* cpu setup		*/
486164080Scognet};
487164080Scognet#endif /* CPU_XSCALE_81342 */
488201468Srpaulo
489201468Srpaulo
490280842Sandrew#if defined(CPU_FA526)
491201468Srpaulostruct cpu_functions fa526_cpufuncs = {
492201468Srpaulo	/* CPU functions */
493201468Srpaulo
494207611Skevlo	cpufunc_id,			/* id			*/
495207611Skevlo	cpufunc_nullop,			/* cpwait		*/
496201468Srpaulo
497201468Srpaulo	/* MMU functions */
498201468Srpaulo
499207611Skevlo	cpufunc_control,		/* control		*/
500207611Skevlo	cpufunc_domains,		/* domain		*/
501207611Skevlo	fa526_setttb,			/* setttb		*/
502207611Skevlo	cpufunc_faultstatus,		/* faultstatus		*/
503207611Skevlo	cpufunc_faultaddress,		/* faultaddress		*/
504201468Srpaulo
505201468Srpaulo	/* TLB functions */
506201468Srpaulo
507207611Skevlo	armv4_tlb_flushID,		/* tlb_flushID		*/
508207611Skevlo	fa526_tlb_flushID_SE,		/* tlb_flushID_SE	*/
509207611Skevlo	armv4_tlb_flushI,		/* tlb_flushI		*/
510207611Skevlo	fa526_tlb_flushI_SE,		/* tlb_flushI_SE	*/
511207611Skevlo	armv4_tlb_flushD,		/* tlb_flushD		*/
512207611Skevlo	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
513201468Srpaulo
514201468Srpaulo	/* Cache operations */
515201468Srpaulo
516207611Skevlo	fa526_icache_sync_all,		/* icache_sync_all	*/
517207611Skevlo	fa526_icache_sync_range,	/* icache_sync_range	*/
518201468Srpaulo
519207611Skevlo	fa526_dcache_wbinv_all,		/* dcache_wbinv_all	*/
520207611Skevlo	fa526_dcache_wbinv_range,	/* dcache_wbinv_range	*/
521207611Skevlo	fa526_dcache_inv_range,		/* dcache_inv_range	*/
522207611Skevlo	fa526_dcache_wb_range,		/* dcache_wb_range	*/
523201468Srpaulo
524262420Sian	armv4_idcache_inv_all,		/* idcache_inv_all	*/
525207611Skevlo	fa526_idcache_wbinv_all,	/* idcache_wbinv_all	*/
526207611Skevlo	fa526_idcache_wbinv_range,	/* idcache_wbinv_range	*/
527207611Skevlo	cpufunc_nullop,			/* l2cache_wbinv_all	*/
528207611Skevlo	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
529207611Skevlo	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
530207611Skevlo	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
531265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
532201468Srpaulo
533201468Srpaulo	/* Other functions */
534201468Srpaulo
535207611Skevlo	fa526_flush_prefetchbuf,	/* flush_prefetchbuf	*/
536207611Skevlo	armv4_drain_writebuf,		/* drain_writebuf	*/
537207611Skevlo	cpufunc_nullop,			/* flush_brnchtgt_C	*/
538207611Skevlo	fa526_flush_brnchtgt_E,		/* flush_brnchtgt_E	*/
539201468Srpaulo
540207611Skevlo	fa526_cpu_sleep,		/* sleep		*/
541201468Srpaulo
542201468Srpaulo	/* Soft functions */
543201468Srpaulo
544207611Skevlo	cpufunc_null_fixup,		/* dataabt_fixup	*/
545207611Skevlo	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
546201468Srpaulo
547207611Skevlo	fa526_context_switch,		/* context_switch	*/
548201468Srpaulo
549207611Skevlo	fa526_setup			/* cpu setup 		*/
550236991Simp};
551280842Sandrew#endif	/* CPU_FA526 */
552201468Srpaulo
553244480Sgonzo#if defined(CPU_ARM1176)
554244480Sgonzostruct cpu_functions arm1176_cpufuncs = {
555244480Sgonzo	/* CPU functions */
556283366Sandrew
557244480Sgonzo	cpufunc_id,                     /* id                   */
558244480Sgonzo	cpufunc_nullop,                 /* cpwait               */
559283366Sandrew
560244480Sgonzo	/* MMU functions */
561283366Sandrew
562244480Sgonzo	cpufunc_control,                /* control              */
563244480Sgonzo	cpufunc_domains,                /* Domain               */
564244480Sgonzo	arm11x6_setttb,                 /* Setttb               */
565244480Sgonzo	cpufunc_faultstatus,            /* Faultstatus          */
566244480Sgonzo	cpufunc_faultaddress,           /* Faultaddress         */
567283366Sandrew
568244480Sgonzo	/* TLB functions */
569283366Sandrew
570244480Sgonzo	arm11_tlb_flushID,              /* tlb_flushID          */
571244480Sgonzo	arm11_tlb_flushID_SE,           /* tlb_flushID_SE       */
572244480Sgonzo	arm11_tlb_flushI,               /* tlb_flushI           */
573244480Sgonzo	arm11_tlb_flushI_SE,            /* tlb_flushI_SE        */
574244480Sgonzo	arm11_tlb_flushD,               /* tlb_flushD           */
575244480Sgonzo	arm11_tlb_flushD_SE,            /* tlb_flushD_SE        */
576283366Sandrew
577244480Sgonzo	/* Cache operations */
578283366Sandrew
579244480Sgonzo	arm11x6_icache_sync_all,        /* icache_sync_all      */
580244480Sgonzo	arm11x6_icache_sync_range,      /* icache_sync_range    */
581283366Sandrew
582244480Sgonzo	arm11x6_dcache_wbinv_all,       /* dcache_wbinv_all     */
583244480Sgonzo	armv6_dcache_wbinv_range,       /* dcache_wbinv_range   */
584244480Sgonzo	armv6_dcache_inv_range,         /* dcache_inv_range     */
585244480Sgonzo	armv6_dcache_wb_range,          /* dcache_wb_range      */
586283366Sandrew
587262420Sian	armv6_idcache_inv_all,		/* idcache_inv_all	*/
588244480Sgonzo	arm11x6_idcache_wbinv_all,      /* idcache_wbinv_all    */
589244480Sgonzo	arm11x6_idcache_wbinv_range,    /* idcache_wbinv_range  */
590283366Sandrew
591244480Sgonzo	(void *)cpufunc_nullop,         /* l2cache_wbinv_all    */
592244480Sgonzo	(void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
593244480Sgonzo	(void *)cpufunc_nullop,         /* l2cache_inv_range    */
594244480Sgonzo	(void *)cpufunc_nullop,         /* l2cache_wb_range     */
595265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
596283366Sandrew
597244480Sgonzo	/* Other functions */
598283366Sandrew
599244480Sgonzo	arm11x6_flush_prefetchbuf,      /* flush_prefetchbuf    */
600244480Sgonzo	arm11_drain_writebuf,           /* drain_writebuf       */
601244480Sgonzo	cpufunc_nullop,                 /* flush_brnchtgt_C     */
602244480Sgonzo	(void *)cpufunc_nullop,         /* flush_brnchtgt_E     */
603283366Sandrew
604244480Sgonzo	arm11x6_sleep,                  /* sleep                */
605283366Sandrew
606244480Sgonzo	/* Soft functions */
607283366Sandrew
608244480Sgonzo	cpufunc_null_fixup,             /* dataabt_fixup        */
609244480Sgonzo	cpufunc_null_fixup,             /* prefetchabt_fixup    */
610283366Sandrew
611244480Sgonzo	arm11_context_switch,           /* context_switch       */
612283366Sandrew
613244480Sgonzo	arm11x6_setup                   /* cpu setup            */
614244480Sgonzo};
615244480Sgonzo#endif /*CPU_ARM1176 */
616239701Sgonzo
617259640Sganbold#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
618239268Sgonzostruct cpu_functions cortexa_cpufuncs = {
619239268Sgonzo	/* CPU functions */
620283366Sandrew
621239268Sgonzo	cpufunc_id,                     /* id                   */
622239268Sgonzo	cpufunc_nullop,                 /* cpwait               */
623283366Sandrew
624239268Sgonzo	/* MMU functions */
625283366Sandrew
626239268Sgonzo	cpufunc_control,                /* control              */
627239268Sgonzo	cpufunc_domains,                /* Domain               */
628239268Sgonzo	armv7_setttb,                   /* Setttb               */
629239268Sgonzo	cpufunc_faultstatus,            /* Faultstatus          */
630239268Sgonzo	cpufunc_faultaddress,           /* Faultaddress         */
631283366Sandrew
632283366Sandrew	/*
633263251Sian	 * TLB functions.  ARMv7 does all TLB ops based on a unified TLB model
634263251Sian	 * whether the hardware implements separate I+D or not, so we use the
635263251Sian	 * same 'ID' functions for all 3 variations.
636263251Sian	 */
637283366Sandrew
638243024Scognet	armv7_tlb_flushID,              /* tlb_flushID          */
639239268Sgonzo	armv7_tlb_flushID_SE,           /* tlb_flushID_SE       */
640263251Sian	armv7_tlb_flushID,              /* tlb_flushI           */
641263251Sian	armv7_tlb_flushID_SE,           /* tlb_flushI_SE        */
642263251Sian	armv7_tlb_flushID,              /* tlb_flushD           */
643263251Sian	armv7_tlb_flushID_SE,           /* tlb_flushD_SE        */
644283366Sandrew
645239268Sgonzo	/* Cache operations */
646283366Sandrew
647264994Sian	armv7_icache_sync_all, 	        /* icache_sync_all      */
648239268Sgonzo	armv7_icache_sync_range,        /* icache_sync_range    */
649283366Sandrew
650239268Sgonzo	armv7_dcache_wbinv_all,         /* dcache_wbinv_all     */
651239268Sgonzo	armv7_dcache_wbinv_range,       /* dcache_wbinv_range   */
652239268Sgonzo	armv7_dcache_inv_range,         /* dcache_inv_range     */
653239268Sgonzo	armv7_dcache_wb_range,          /* dcache_wb_range      */
654283366Sandrew
655262420Sian	armv7_idcache_inv_all,		/* idcache_inv_all	*/
656239268Sgonzo	armv7_idcache_wbinv_all,        /* idcache_wbinv_all    */
657239268Sgonzo	armv7_idcache_wbinv_range,      /* idcache_wbinv_range  */
658283366Sandrew
659283366Sandrew	/*
660243026Scognet	 * Note: For CPUs using the PL310 the L2 ops are filled in when the
661239268Sgonzo	 * L2 cache controller is actually enabled.
662239268Sgonzo	 */
663239268Sgonzo	cpufunc_nullop,                 /* l2cache_wbinv_all    */
664239268Sgonzo	(void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
665239268Sgonzo	(void *)cpufunc_nullop,         /* l2cache_inv_range    */
666239268Sgonzo	(void *)cpufunc_nullop,         /* l2cache_wb_range     */
667265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
668283366Sandrew
669239268Sgonzo	/* Other functions */
670283366Sandrew
671239268Sgonzo	cpufunc_nullop,                 /* flush_prefetchbuf    */
672245478Scognet	armv7_drain_writebuf,           /* drain_writebuf       */
673239268Sgonzo	cpufunc_nullop,                 /* flush_brnchtgt_C     */
674239268Sgonzo	(void *)cpufunc_nullop,         /* flush_brnchtgt_E     */
675283366Sandrew
676282934Sganbold	armv7_cpu_sleep,                /* sleep                */
677283366Sandrew
678239268Sgonzo	/* Soft functions */
679283366Sandrew
680239268Sgonzo	cpufunc_null_fixup,             /* dataabt_fixup        */
681239268Sgonzo	cpufunc_null_fixup,             /* prefetchabt_fixup    */
682283366Sandrew
683245478Scognet	armv7_context_switch,           /* context_switch       */
684283366Sandrew
685239268Sgonzo	cortexa_setup                     /* cpu setup            */
686239268Sgonzo};
687239268Sgonzo#endif /* CPU_CORTEXA */
688201468Srpaulo
689129198Scognet/*
690129198Scognet * Global constants also used by locore.s
691129198Scognet */
692129198Scognet
693129198Scognetstruct cpu_functions cpufuncs;
694129198Scognetu_int cputype;
695129198Scognetu_int cpu_reset_needs_v4_MMU_disable;	/* flag used in locore.s */
696129198Scognet
697262958Sian#if defined(CPU_ARM9) ||	\
698280824Sandrew  defined (CPU_ARM9E) ||	\
699280847Sandrew  defined(CPU_ARM1176) || defined(CPU_XSCALE_80321) ||		\
700207611Skevlo  defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) ||		\
701280842Sandrew  defined(CPU_FA526) || defined(CPU_MV_PJ4B) ||			\
702239268Sgonzo  defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \
703259640Sganbold  defined(CPU_CORTEXA) || defined(CPU_KRAIT)
704161592Scognet
705278518Szbb/* Global cache line sizes, use 32 as default */
706278518Szbbint	arm_dcache_min_line_size = 32;
707278518Szbbint	arm_icache_min_line_size = 32;
708278518Szbbint	arm_idcache_min_line_size = 32;
709278518Szbb
710137498Strhodesstatic void get_cachetype_cp15(void);
711129198Scognet
712129198Scognet/* Additional cache information local to this file.  Log2 of some of the
713129198Scognet   above numbers.  */
714129198Scognetstatic int	arm_dcache_l2_nsets;
715129198Scognetstatic int	arm_dcache_l2_assoc;
716129198Scognetstatic int	arm_dcache_l2_linesize;
717129198Scognet
718129198Scognetstatic void
719129198Scognetget_cachetype_cp15()
720129198Scognet{
721239268Sgonzo	u_int ctype, isize, dsize, cpuid;
722239268Sgonzo	u_int clevel, csize, i, sel;
723129198Scognet	u_int multiplier;
724239268Sgonzo	u_char type;
725129198Scognet
726129198Scognet	__asm __volatile("mrc p15, 0, %0, c0, c0, 1"
727129198Scognet		: "=r" (ctype));
728129198Scognet
729239268Sgonzo	cpuid = cpufunc_id();
730129198Scognet	/*
731129198Scognet	 * ...and thus spake the ARM ARM:
732129198Scognet	 *
733129198Scognet	 * If an <opcode2> value corresponding to an unimplemented or
734129198Scognet	 * reserved ID register is encountered, the System Control
735129198Scognet	 * processor returns the value of the main ID register.
736129198Scognet	 */
737239268Sgonzo	if (ctype == cpuid)
738129198Scognet		goto out;
739129198Scognet
740239268Sgonzo	if (CPU_CT_FORMAT(ctype) == CPU_CT_ARMV7) {
741278518Szbb		/* Resolve minimal cache line sizes */
742278518Szbb		arm_dcache_min_line_size = 1 << (CPU_CT_DMINLINE(ctype) + 2);
743278518Szbb		arm_icache_min_line_size = 1 << (CPU_CT_IMINLINE(ctype) + 2);
744278518Szbb		arm_idcache_min_line_size =
745278518Szbb		    min(arm_icache_min_line_size, arm_dcache_min_line_size);
746278518Szbb
747239268Sgonzo		__asm __volatile("mrc p15, 1, %0, c0, c0, 1"
748239268Sgonzo		    : "=r" (clevel));
749239268Sgonzo		arm_cache_level = clevel;
750239268Sgonzo		arm_cache_loc = CPU_CLIDR_LOC(arm_cache_level);
751239268Sgonzo		i = 0;
752239268Sgonzo		while ((type = (clevel & 0x7)) && i < 7) {
753239268Sgonzo			if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
754239268Sgonzo			    type == CACHE_SEP_CACHE) {
755239268Sgonzo				sel = i << 1;
756239268Sgonzo				__asm __volatile("mcr p15, 2, %0, c0, c0, 0"
757239268Sgonzo				    : : "r" (sel));
758239268Sgonzo				__asm __volatile("mrc p15, 1, %0, c0, c0, 0"
759239268Sgonzo				    : "=r" (csize));
760239268Sgonzo				arm_cache_type[sel] = csize;
761283366Sandrew				arm_dcache_align = 1 <<
762239268Sgonzo				    (CPUV7_CT_xSIZE_LEN(csize) + 4);
763239268Sgonzo				arm_dcache_align_mask = arm_dcache_align - 1;
764239268Sgonzo			}
765239268Sgonzo			if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
766239268Sgonzo				sel = (i << 1) | 1;
767239268Sgonzo				__asm __volatile("mcr p15, 2, %0, c0, c0, 0"
768239268Sgonzo				    : : "r" (sel));
769239268Sgonzo				__asm __volatile("mrc p15, 1, %0, c0, c0, 0"
770239268Sgonzo				    : "=r" (csize));
771239268Sgonzo				arm_cache_type[sel] = csize;
772239268Sgonzo			}
773239268Sgonzo			i++;
774239268Sgonzo			clevel >>= 3;
775239268Sgonzo		}
776239268Sgonzo	} else {
777239268Sgonzo		if ((ctype & CPU_CT_S) == 0)
778239268Sgonzo			arm_pcache_unified = 1;
779129198Scognet
780239268Sgonzo		/*
781239268Sgonzo		 * If you want to know how this code works, go read the ARM ARM.
782239268Sgonzo		 */
783129198Scognet
784239268Sgonzo		arm_pcache_type = CPU_CT_CTYPE(ctype);
785129198Scognet
786239268Sgonzo		if (arm_pcache_unified == 0) {
787239268Sgonzo			isize = CPU_CT_ISIZE(ctype);
788239268Sgonzo			multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2;
789239268Sgonzo			arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3);
790239268Sgonzo			if (CPU_CT_xSIZE_ASSOC(isize) == 0) {
791239268Sgonzo				if (isize & CPU_CT_xSIZE_M)
792239268Sgonzo					arm_picache_line_size = 0; /* not present */
793239268Sgonzo				else
794239268Sgonzo					arm_picache_ways = 1;
795239268Sgonzo			} else {
796239268Sgonzo				arm_picache_ways = multiplier <<
797239268Sgonzo				    (CPU_CT_xSIZE_ASSOC(isize) - 1);
798239268Sgonzo			}
799239268Sgonzo			arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
800239268Sgonzo		}
801239268Sgonzo
802239268Sgonzo		dsize = CPU_CT_DSIZE(ctype);
803239268Sgonzo		multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
804239268Sgonzo		arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
805239268Sgonzo		if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
806239268Sgonzo			if (dsize & CPU_CT_xSIZE_M)
807239268Sgonzo				arm_pdcache_line_size = 0; /* not present */
808129198Scognet			else
809239268Sgonzo				arm_pdcache_ways = 1;
810129198Scognet		} else {
811239268Sgonzo			arm_pdcache_ways = multiplier <<
812239268Sgonzo			    (CPU_CT_xSIZE_ASSOC(dsize) - 1);
813129198Scognet		}
814239268Sgonzo		arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
815129198Scognet
816239268Sgonzo		arm_dcache_align = arm_pdcache_line_size;
817129198Scognet
818239268Sgonzo		arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2;
819239268Sgonzo		arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3;
820239268Sgonzo		arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) -
821239268Sgonzo		    CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize);
822129198Scognet
823239268Sgonzo	out:
824239268Sgonzo		arm_dcache_align_mask = arm_dcache_align - 1;
825239268Sgonzo	}
826129198Scognet}
827262958Sian#endif /* ARM9 || XSCALE */
828129198Scognet
829129198Scognet/*
830129198Scognet * Cannot panic here as we may not have a console yet ...
831129198Scognet */
832129198Scognet
833129198Scognetint
834129198Scognetset_cpufuncs()
835129198Scognet{
836129198Scognet	cputype = cpufunc_id();
837129198Scognet	cputype &= CPU_ID_CPU_MASK;
838129198Scognet
839129198Scognet#ifdef CPU_ARM9
840129198Scognet	if (((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD ||
841129198Scognet	     (cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_TI) &&
842129198Scognet	    (cputype & 0x0000f000) == 0x00009000) {
843129198Scognet		cpufuncs = arm9_cpufuncs;
844129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* V4 or higher */
845129198Scognet		get_cachetype_cp15();
846146605Scognet		arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize;
847146605Scognet		arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize +
848146605Scognet		    arm_dcache_l2_nsets)) - arm9_dcache_sets_inc;
849146605Scognet		arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc);
850146605Scognet		arm9_dcache_index_max = 0U - arm9_dcache_index_inc;
851137270Scognet		pmap_pte_init_generic();
852166655Scognet		goto out;
853129198Scognet	}
854129198Scognet#endif /* CPU_ARM9 */
855280809Sandrew#if defined(CPU_ARM9E)
856239268Sgonzo	if (cputype == CPU_ID_MV88FR131 || cputype == CPU_ID_MV88FR571_VD ||
857183835Sraj	    cputype == CPU_ID_MV88FR571_41) {
858239268Sgonzo		uint32_t sheeva_ctrl;
859183835Sraj
860239268Sgonzo		sheeva_ctrl = (MV_DC_STREAM_ENABLE | MV_BTB_DISABLE |
861239268Sgonzo		    MV_L2_ENABLE);
862239268Sgonzo		/*
863239268Sgonzo		 * Workaround for Marvell MV78100 CPU: Cache prefetch
864239268Sgonzo		 * mechanism may affect the cache coherency validity,
865239268Sgonzo		 * so it needs to be disabled.
866239268Sgonzo		 *
867239268Sgonzo		 * Refer to errata document MV-S501058-00C.pdf (p. 3.1
868239268Sgonzo		 * L2 Prefetching Mechanism) for details.
869239268Sgonzo		 */
870239268Sgonzo		if (cputype == CPU_ID_MV88FR571_VD ||
871239268Sgonzo		    cputype == CPU_ID_MV88FR571_41)
872239268Sgonzo			sheeva_ctrl |= MV_L2_PREFETCH_DISABLE;
873212825Smav
874239268Sgonzo		sheeva_control_ext(0xffffffff & ~MV_WA_ENABLE, sheeva_ctrl);
875183835Sraj
876239268Sgonzo		cpufuncs = sheeva_cpufuncs;
877172738Simp		get_cachetype_cp15();
878172738Simp		pmap_pte_init_generic();
879174058Scognet		goto out;
880280809Sandrew	} else if (cputype == CPU_ID_ARM926EJS) {
881239268Sgonzo		cpufuncs = armv5_ec_cpufuncs;
882239268Sgonzo		get_cachetype_cp15();
883239268Sgonzo		pmap_pte_init_generic();
884239268Sgonzo		goto out;
885172738Simp	}
886280809Sandrew#endif /* CPU_ARM9E */
887280824Sandrew#if defined(CPU_ARM1176)
888280824Sandrew	if (cputype == CPU_ID_ARM1176JZS) {
889280868Sandrew		cpufuncs = arm1176_cpufuncs;
890244480Sgonzo		cpu_reset_needs_v4_MMU_disable = 1;     /* V4 or higher */
891244480Sgonzo		get_cachetype_cp15();
892239701Sgonzo
893244480Sgonzo		pmap_pte_init_mmu_v6();
894244480Sgonzo
895244480Sgonzo		goto out;
896244480Sgonzo	}
897280824Sandrew#endif /* CPU_ARM1176 */
898259640Sganbold#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
899256629Sbr	if (cputype == CPU_ID_CORTEXA5 ||
900256629Sbr	    cputype == CPU_ID_CORTEXA7 ||
901253857Sganbold	    cputype == CPU_ID_CORTEXA8R1 ||
902239268Sgonzo	    cputype == CPU_ID_CORTEXA8R2 ||
903239268Sgonzo	    cputype == CPU_ID_CORTEXA8R3 ||
904239268Sgonzo	    cputype == CPU_ID_CORTEXA9R1 ||
905249999Swkoszek	    cputype == CPU_ID_CORTEXA9R2 ||
906252361Sray	    cputype == CPU_ID_CORTEXA9R3 ||
907277156Sganbold	    cputype == CPU_ID_CORTEXA12R0 ||
908263982Sbr	    cputype == CPU_ID_CORTEXA15R0 ||
909263982Sbr	    cputype == CPU_ID_CORTEXA15R1 ||
910263982Sbr	    cputype == CPU_ID_CORTEXA15R2 ||
911263982Sbr	    cputype == CPU_ID_CORTEXA15R3 ||
912259640Sganbold	    cputype == CPU_ID_KRAIT ) {
913239268Sgonzo		cpufuncs = cortexa_cpufuncs;
914239268Sgonzo		cpu_reset_needs_v4_MMU_disable = 1;     /* V4 or higher */
915239268Sgonzo		get_cachetype_cp15();
916283366Sandrew
917239268Sgonzo		pmap_pte_init_mmu_v6();
918239268Sgonzo		goto out;
919239268Sgonzo	}
920239268Sgonzo#endif /* CPU_CORTEXA */
921283366Sandrew
922239268Sgonzo#if defined(CPU_MV_PJ4B)
923257281Szbb	if (cputype == CPU_ID_MV88SV581X_V7 ||
924240486Sgber	    cputype == CPU_ID_MV88SV584X_V7 ||
925239268Sgonzo	    cputype == CPU_ID_ARM_88SV581X_V7) {
926257281Szbb		cpufuncs = pj4bv7_cpufuncs;
927239268Sgonzo		get_cachetype_cp15();
928239268Sgonzo		pmap_pte_init_mmu_v6();
929239268Sgonzo		goto out;
930239268Sgonzo	}
931239268Sgonzo#endif /* CPU_MV_PJ4B */
932129198Scognet
933280842Sandrew#if defined(CPU_FA526)
934207611Skevlo	if (cputype == CPU_ID_FA526 || cputype == CPU_ID_FA626TE) {
935201468Srpaulo		cpufuncs = fa526_cpufuncs;
936201468Srpaulo		cpu_reset_needs_v4_MMU_disable = 1;	/* SA needs it	*/
937201468Srpaulo		get_cachetype_cp15();
938201468Srpaulo		pmap_pte_init_generic();
939201468Srpaulo
940201468Srpaulo		goto out;
941201468Srpaulo	}
942280842Sandrew#endif	/* CPU_FA526 */
943262958Sian
944161592Scognet#if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219)
945129198Scognet	if (cputype == CPU_ID_80321_400 || cputype == CPU_ID_80321_600 ||
946161592Scognet	    cputype == CPU_ID_80321_400_B0 || cputype == CPU_ID_80321_600_B0 ||
947161592Scognet	    cputype == CPU_ID_80219_400 || cputype == CPU_ID_80219_600) {
948129198Scognet		cpufuncs = xscale_cpufuncs;
949129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
950129198Scognet		get_cachetype_cp15();
951129198Scognet		pmap_pte_init_xscale();
952166655Scognet		goto out;
953129198Scognet	}
954129198Scognet#endif /* CPU_XSCALE_80321 */
955161592Scognet
956164080Scognet#if defined(CPU_XSCALE_81342)
957164080Scognet	if (cputype == CPU_ID_81342) {
958164080Scognet		cpufuncs = xscalec3_cpufuncs;
959164080Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
960164080Scognet		get_cachetype_cp15();
961164080Scognet		pmap_pte_init_xscale();
962166655Scognet		goto out;
963164080Scognet	}
964164080Scognet#endif /* CPU_XSCALE_81342 */
965129198Scognet#ifdef CPU_XSCALE_PXA2X0
966129198Scognet	/* ignore core revision to test PXA2xx CPUs */
967129198Scognet	if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA250 ||
968191817Sstas	    (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X ||
969129198Scognet	    (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA210) {
970129198Scognet
971129198Scognet		cpufuncs = xscale_cpufuncs;
972129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
973129198Scognet		get_cachetype_cp15();
974129198Scognet		pmap_pte_init_xscale();
975129198Scognet
976166655Scognet		goto out;
977129198Scognet	}
978129198Scognet#endif /* CPU_XSCALE_PXA2X0 */
979129198Scognet#ifdef CPU_XSCALE_IXP425
980129198Scognet	if (cputype == CPU_ID_IXP425_533 || cputype == CPU_ID_IXP425_400 ||
981186352Ssam            cputype == CPU_ID_IXP425_266 || cputype == CPU_ID_IXP435) {
982129198Scognet
983129198Scognet		cpufuncs = xscale_cpufuncs;
984129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
985129198Scognet		get_cachetype_cp15();
986129198Scognet		pmap_pte_init_xscale();
987129198Scognet
988166655Scognet		goto out;
989129198Scognet	}
990129198Scognet#endif /* CPU_XSCALE_IXP425 */
991129198Scognet	/*
992129198Scognet	 * Bzzzz. And the answer was ...
993129198Scognet	 */
994129198Scognet	panic("No support for this CPU type (%08x) in kernel", cputype);
995129198Scognet	return(ARCHITECTURE_NOT_PRESENT);
996166655Scognetout:
997166655Scognet	uma_set_align(arm_dcache_align_mask);
998166655Scognet	return (0);
999129198Scognet}
1000129198Scognet
1001129198Scognet/*
1002129198Scognet * Fixup routines for data and prefetch aborts.
1003129198Scognet *
1004129198Scognet * Several compile time symbols are used
1005129198Scognet *
1006129198Scognet * DEBUG_FAULT_CORRECTION - Print debugging information during the
1007129198Scognet * correction of registers after a fault.
1008129198Scognet */
1009129198Scognet
1010129198Scognet
1011129198Scognet/*
1012129198Scognet * Null abort fixup routine.
1013129198Scognet * For use when no fixup is required.
1014129198Scognet */
1015129198Scognetint
1016129198Scognetcpufunc_null_fixup(arg)
1017129198Scognet	void *arg;
1018129198Scognet{
1019129198Scognet	return(ABORT_FIXUP_OK);
1020129198Scognet}
1021129198Scognet
1022129198Scognet/*
1023129198Scognet * CPU Setup code
1024129198Scognet */
1025129198Scognet
1026129198Scognet#ifdef CPU_ARM9
1027129198Scognetvoid
1028280823Sandrewarm9_setup(void)
1029129198Scognet{
1030129198Scognet	int cpuctrl, cpuctrlmask;
1031129198Scognet
1032129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1033129198Scognet	    | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1034129198Scognet	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1035157618Scognet	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE |
1036157618Scognet	    CPU_CONTROL_ROUNDROBIN;
1037129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1038129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1039129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1040129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
1041129198Scognet		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
1042146605Scognet		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_VECRELOC
1043146605Scognet		 | CPU_CONTROL_ROUNDROBIN;
1044129198Scognet
1045129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1046129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1047129198Scognet#endif
1048129198Scognet
1049129198Scognet#ifdef __ARMEB__
1050129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1051129198Scognet#endif
1052142050Scognet	if (vector_page == ARM_VECTORS_HIGH)
1053142050Scognet		cpuctrl |= CPU_CONTROL_VECRELOC;
1054129198Scognet
1055129198Scognet	/* Clear out the cache */
1056129198Scognet	cpu_idcache_wbinv_all();
1057129198Scognet
1058129198Scognet	/* Set the control register */
1059146605Scognet	cpu_control(cpuctrlmask, cpuctrl);
1060129198Scognet	ctrl = cpuctrl;
1061129198Scognet
1062129198Scognet}
1063129198Scognet#endif	/* CPU_ARM9 */
1064129198Scognet
1065280809Sandrew#if defined(CPU_ARM9E)
1066129198Scognetvoid
1067280823Sandrewarm10_setup(void)
1068129198Scognet{
1069129198Scognet	int cpuctrl, cpuctrlmask;
1070129198Scognet
1071129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
1072236991Simp	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1073129198Scognet	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE;
1074129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
1075129198Scognet	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1076129198Scognet	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
1077129198Scognet	    | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
1078129198Scognet	    | CPU_CONTROL_BPRD_ENABLE
1079129198Scognet	    | CPU_CONTROL_ROUNDROBIN | CPU_CONTROL_CPCLK;
1080129198Scognet
1081129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1082129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1083129198Scognet#endif
1084129198Scognet
1085129198Scognet#ifdef __ARMEB__
1086129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1087129198Scognet#endif
1088129198Scognet
1089129198Scognet	/* Clear out the cache */
1090129198Scognet	cpu_idcache_wbinv_all();
1091129198Scognet
1092129198Scognet	/* Now really make sure they are clean.  */
1093172738Simp	__asm __volatile ("mcr\tp15, 0, r0, c7, c7, 0" : : );
1094129198Scognet
1095174058Scognet	if (vector_page == ARM_VECTORS_HIGH)
1096174058Scognet		cpuctrl |= CPU_CONTROL_VECRELOC;
1097174058Scognet
1098129198Scognet	/* Set the control register */
1099129198Scognet	ctrl = cpuctrl;
1100129198Scognet	cpu_control(0xffffffff, cpuctrl);
1101129198Scognet
1102129198Scognet	/* And again. */
1103129198Scognet	cpu_idcache_wbinv_all();
1104129198Scognet}
1105172738Simp#endif	/* CPU_ARM9E || CPU_ARM10 */
1106129198Scognet
1107280824Sandrew#if defined(CPU_ARM1176) \
1108266083Smarkm || defined(CPU_MV_PJ4B) \
1109266083Smarkm || defined(CPU_CORTEXA) || defined(CPU_KRAIT)
1110266083Smarkmstatic __inline void
1111266083Smarkmcpu_scc_setup_ccnt(void)
1112266083Smarkm{
1113266083Smarkm/* This is how you give userland access to the CCNT and PMCn
1114266083Smarkm * registers.
1115266083Smarkm * BEWARE! This gives write access also, which may not be what
1116266083Smarkm * you want!
1117266083Smarkm */
1118266083Smarkm#ifdef _PMC_USER_READ_WRITE_
1119266083Smarkm	/* Set PMUSERENR[0] to allow userland access */
1120283365Sandrew	cp15_pmuserenr_set(1);
1121266083Smarkm#endif
1122280824Sandrew#if defined(CPU_ARM1176)
1123267597Stuexen	/* Set PMCR[2,0] to enable counters and reset CCNT */
1124283365Sandrew	cp15_pmcr_set(5);
1125267597Stuexen#else
1126267597Stuexen	/* Set up the PMCCNTR register as a cyclecounter:
1127266083Smarkm	 * Set PMINTENCLR to 0xFFFFFFFF to block interrupts
1128266083Smarkm	 * Set PMCR[2,0] to enable counters and reset CCNT
1129266083Smarkm	 * Set PMCNTENSET to 0x80000000 to enable CCNT */
1130283365Sandrew	cp15_pminten_clr(0xFFFFFFFF);
1131283365Sandrew	cp15_pmcr_set(5);
1132283365Sandrew	cp15_pmcnten_set(0x80000000);
1133267597Stuexen#endif
1134266083Smarkm}
1135266083Smarkm#endif
1136266083Smarkm
1137280824Sandrew#if defined(CPU_ARM1176)
1138172738Simpvoid
1139280823Sandrewarm11x6_setup(void)
1140172738Simp{
1141244480Sgonzo	int cpuctrl, cpuctrl_wax;
1142244480Sgonzo	uint32_t auxctrl, auxctrl_wax;
1143244480Sgonzo	uint32_t tmp, tmp2;
1144244480Sgonzo	uint32_t sbz=0;
1145244480Sgonzo	uint32_t cpuid;
1146172738Simp
1147244480Sgonzo	cpuid = cpufunc_id();
1148244480Sgonzo
1149244480Sgonzo	cpuctrl =
1150244480Sgonzo		CPU_CONTROL_MMU_ENABLE  |
1151244480Sgonzo		CPU_CONTROL_DC_ENABLE   |
1152244480Sgonzo		CPU_CONTROL_WBUF_ENABLE |
1153244480Sgonzo		CPU_CONTROL_32BP_ENABLE |
1154244480Sgonzo		CPU_CONTROL_32BD_ENABLE |
1155244480Sgonzo		CPU_CONTROL_LABT_ENABLE |
1156244480Sgonzo		CPU_CONTROL_SYST_ENABLE |
1157282019Sandrew		CPU_CONTROL_IC_ENABLE   |
1158282019Sandrew		CPU_CONTROL_UNAL_ENABLE;
1159244480Sgonzo
1160244480Sgonzo	/*
1161244480Sgonzo	 * "write as existing" bits
1162244480Sgonzo	 * inverse of this is mask
1163244480Sgonzo	 */
1164244480Sgonzo	cpuctrl_wax =
1165244480Sgonzo		(3 << 30) | /* SBZ */
1166244480Sgonzo		(1 << 29) | /* FA */
1167244480Sgonzo		(1 << 28) | /* TR */
1168283366Sandrew		(3 << 26) | /* SBZ */
1169244480Sgonzo		(3 << 19) | /* SBZ */
1170244480Sgonzo		(1 << 17);  /* SBZ */
1171244480Sgonzo
1172244480Sgonzo	cpuctrl |= CPU_CONTROL_BPRD_ENABLE;
1173244480Sgonzo	cpuctrl |= CPU_CONTROL_V6_EXTPAGE;
1174244480Sgonzo
1175172738Simp#ifdef __ARMEB__
1176172738Simp	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1177172738Simp#endif
1178244480Sgonzo
1179239701Sgonzo	if (vector_page == ARM_VECTORS_HIGH)
1180239701Sgonzo		cpuctrl |= CPU_CONTROL_VECRELOC;
1181172738Simp
1182244480Sgonzo	auxctrl = 0;
1183244480Sgonzo	auxctrl_wax = ~0;
1184244480Sgonzo
1185244480Sgonzo	/*
1186244480Sgonzo	 * Enable an errata workaround
1187244480Sgonzo	 */
1188244480Sgonzo	if ((cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM1176JZS) { /* ARM1176JZSr0 */
1189244480Sgonzo		auxctrl = ARM1176_AUXCTL_PHD;
1190244480Sgonzo		auxctrl_wax = ~ARM1176_AUXCTL_PHD;
1191244480Sgonzo	}
1192244480Sgonzo
1193244480Sgonzo	/* Clear out the cache */
1194172738Simp	cpu_idcache_wbinv_all();
1195172738Simp
1196244480Sgonzo	/* Now really make sure they are clean.  */
1197244480Sgonzo	__asm volatile ("mcr\tp15, 0, %0, c7, c7, 0" : : "r"(sbz));
1198244480Sgonzo
1199244480Sgonzo	/* Allow detection code to find the VFP if it's fitted.  */
1200283365Sandrew	cp15_cpacr_set(0x0fffffff);
1201244480Sgonzo
1202172738Simp	/* Set the control register */
1203239701Sgonzo	ctrl = cpuctrl;
1204244480Sgonzo	cpu_control(~cpuctrl_wax, cpuctrl);
1205172738Simp
1206283365Sandrew	tmp = cp15_actlr_get();
1207283365Sandrew	tmp2 = tmp;
1208283365Sandrew	tmp &= auxctrl_wax;
1209283365Sandrew	tmp |= auxctrl;
1210283365Sandrew	if (tmp != tmp2)
1211283365Sandrew		cp15_actlr_set(tmp);
1212244480Sgonzo
1213244480Sgonzo	/* And again. */
1214172738Simp	cpu_idcache_wbinv_all();
1215266083Smarkm
1216266083Smarkm	cpu_scc_setup_ccnt();
1217172738Simp}
1218280824Sandrew#endif  /* CPU_ARM1176 */
1219172738Simp
1220239268Sgonzo#ifdef CPU_MV_PJ4B
1221239268Sgonzovoid
1222280823Sandrewpj4bv7_setup(void)
1223239268Sgonzo{
1224239268Sgonzo	int cpuctrl;
1225239268Sgonzo
1226239268Sgonzo	pj4b_config();
1227239268Sgonzo
1228239268Sgonzo	cpuctrl = CPU_CONTROL_MMU_ENABLE;
1229239268Sgonzo#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1230239268Sgonzo	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1231239268Sgonzo#endif
1232239268Sgonzo	cpuctrl |= CPU_CONTROL_DC_ENABLE;
1233239268Sgonzo	cpuctrl |= (0xf << 3);
1234239268Sgonzo	cpuctrl |= CPU_CONTROL_BPRD_ENABLE;
1235239268Sgonzo	cpuctrl |= CPU_CONTROL_IC_ENABLE;
1236239268Sgonzo	if (vector_page == ARM_VECTORS_HIGH)
1237239268Sgonzo		cpuctrl |= CPU_CONTROL_VECRELOC;
1238239268Sgonzo	cpuctrl |= (0x5 << 16) | (1 < 22);
1239239268Sgonzo	cpuctrl |= CPU_CONTROL_V6_EXTPAGE;
1240239268Sgonzo
1241239268Sgonzo	/* Clear out the cache */
1242239268Sgonzo	cpu_idcache_wbinv_all();
1243239268Sgonzo
1244239268Sgonzo	/* Set the control register */
1245239268Sgonzo	ctrl = cpuctrl;
1246239268Sgonzo	cpu_control(0xFFFFFFFF, cpuctrl);
1247239268Sgonzo
1248239268Sgonzo	/* And again. */
1249239268Sgonzo	cpu_idcache_wbinv_all();
1250266083Smarkm
1251266083Smarkm	cpu_scc_setup_ccnt();
1252239268Sgonzo}
1253239268Sgonzo#endif /* CPU_MV_PJ4B */
1254239268Sgonzo
1255259640Sganbold#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
1256239268Sgonzo
1257239268Sgonzovoid
1258280823Sandrewcortexa_setup(void)
1259239268Sgonzo{
1260239268Sgonzo	int cpuctrl, cpuctrlmask;
1261283366Sandrew
1262239268Sgonzo	cpuctrlmask = CPU_CONTROL_MMU_ENABLE |     /* MMU enable         [0] */
1263239268Sgonzo	    CPU_CONTROL_AFLT_ENABLE |    /* Alignment fault    [1] */
1264239268Sgonzo	    CPU_CONTROL_DC_ENABLE |      /* DCache enable      [2] */
1265239268Sgonzo	    CPU_CONTROL_BPRD_ENABLE |    /* Branch prediction [11] */
1266239268Sgonzo	    CPU_CONTROL_IC_ENABLE |      /* ICache enable     [12] */
1267239268Sgonzo	    CPU_CONTROL_VECRELOC;        /* Vector relocation [13] */
1268283366Sandrew
1269239268Sgonzo	cpuctrl = CPU_CONTROL_MMU_ENABLE |
1270239268Sgonzo	    CPU_CONTROL_IC_ENABLE |
1271239268Sgonzo	    CPU_CONTROL_DC_ENABLE |
1272239268Sgonzo	    CPU_CONTROL_BPRD_ENABLE;
1273283366Sandrew
1274239268Sgonzo#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1275239268Sgonzo	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1276239268Sgonzo#endif
1277283366Sandrew
1278239268Sgonzo	/* Switch to big endian */
1279239268Sgonzo#ifdef __ARMEB__
1280239268Sgonzo	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1281239268Sgonzo#endif
1282283366Sandrew
1283239268Sgonzo	/* Check if the vector page is at the high address (0xffff0000) */
1284239268Sgonzo	if (vector_page == ARM_VECTORS_HIGH)
1285239268Sgonzo		cpuctrl |= CPU_CONTROL_VECRELOC;
1286283366Sandrew
1287239268Sgonzo	/* Clear out the cache */
1288239268Sgonzo	cpu_idcache_wbinv_all();
1289283366Sandrew
1290239268Sgonzo	/* Set the control register */
1291239268Sgonzo	ctrl = cpuctrl;
1292239268Sgonzo	cpu_control(cpuctrlmask, cpuctrl);
1293283366Sandrew
1294239268Sgonzo	/* And again. */
1295239268Sgonzo	cpu_idcache_wbinv_all();
1296239268Sgonzo#ifdef SMP
1297239268Sgonzo	armv7_auxctrl((1 << 6) | (1 << 0), (1 << 6) | (1 << 0)); /* Enable SMP + TLB broadcasting  */
1298239268Sgonzo#endif
1299266083Smarkm
1300266083Smarkm	cpu_scc_setup_ccnt();
1301239268Sgonzo}
1302239268Sgonzo#endif  /* CPU_CORTEXA */
1303239268Sgonzo
1304280842Sandrew#if defined(CPU_FA526)
1305201468Srpaulovoid
1306280823Sandrewfa526_setup(void)
1307201468Srpaulo{
1308201468Srpaulo	int cpuctrl, cpuctrlmask;
1309201468Srpaulo
1310201468Srpaulo	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1311201468Srpaulo		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1312201468Srpaulo		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1313204122Skevlo		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
1314204122Skevlo		| CPU_CONTROL_BPRD_ENABLE;
1315201468Srpaulo	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1316201468Srpaulo		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1317201468Srpaulo		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1318201468Srpaulo		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
1319201468Srpaulo		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
1320201468Srpaulo		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
1321201468Srpaulo		 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC;
1322201468Srpaulo
1323201468Srpaulo#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1324201468Srpaulo	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1325201468Srpaulo#endif
1326201468Srpaulo
1327201468Srpaulo#ifdef __ARMEB__
1328201468Srpaulo	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1329201468Srpaulo#endif
1330201468Srpaulo
1331201468Srpaulo	if (vector_page == ARM_VECTORS_HIGH)
1332201468Srpaulo		cpuctrl |= CPU_CONTROL_VECRELOC;
1333201468Srpaulo
1334201468Srpaulo	/* Clear out the cache */
1335201468Srpaulo	cpu_idcache_wbinv_all();
1336201468Srpaulo
1337201468Srpaulo	/* Set the control register */
1338201468Srpaulo	ctrl = cpuctrl;
1339201468Srpaulo	cpu_control(0xffffffff, cpuctrl);
1340201468Srpaulo}
1341280842Sandrew#endif	/* CPU_FA526 */
1342201468Srpaulo
1343280847Sandrew#if defined(CPU_XSCALE_80321) || \
1344161592Scognet  defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
1345164080Scognet  defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)
1346129198Scognetvoid
1347280823Sandrewxscale_setup(void)
1348129198Scognet{
1349129198Scognet	uint32_t auxctl;
1350129198Scognet	int cpuctrl, cpuctrlmask;
1351129198Scognet
1352129198Scognet	/*
1353129198Scognet	 * The XScale Write Buffer is always enabled.  Our option
1354129198Scognet	 * is to enable/disable coalescing.  Note that bits 6:3
1355129198Scognet	 * must always be enabled.
1356129198Scognet	 */
1357129198Scognet
1358129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1359129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1360129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1361129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
1362129198Scognet		 | CPU_CONTROL_BPRD_ENABLE;
1363129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1364129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1365129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1366129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
1367129198Scognet		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
1368129198Scognet		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
1369171618Scognet		 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC | \
1370171618Scognet		 CPU_CONTROL_L2_ENABLE;
1371129198Scognet
1372129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1373129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1374129198Scognet#endif
1375129198Scognet
1376129198Scognet#ifdef __ARMEB__
1377129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1378129198Scognet#endif
1379129198Scognet
1380129198Scognet	if (vector_page == ARM_VECTORS_HIGH)
1381129198Scognet		cpuctrl |= CPU_CONTROL_VECRELOC;
1382171618Scognet#ifdef CPU_XSCALE_CORE3
1383171618Scognet	cpuctrl |= CPU_CONTROL_L2_ENABLE;
1384171618Scognet#endif
1385129198Scognet
1386129198Scognet	/* Clear out the cache */
1387129198Scognet	cpu_idcache_wbinv_all();
1388129198Scognet
1389129198Scognet	/*
1390129198Scognet	 * Set the control register.  Note that bits 6:3 must always
1391129198Scognet	 * be set to 1.
1392129198Scognet	 */
1393129198Scognet	ctrl = cpuctrl;
1394129198Scognet/*	cpu_control(cpuctrlmask, cpuctrl);*/
1395129198Scognet	cpu_control(0xffffffff, cpuctrl);
1396129198Scognet
1397129198Scognet	/* Make sure write coalescing is turned on */
1398129198Scognet	__asm __volatile("mrc p15, 0, %0, c1, c0, 1"
1399129198Scognet		: "=r" (auxctl));
1400129198Scognet#ifdef XSCALE_NO_COALESCE_WRITES
1401129198Scognet	auxctl |= XSCALE_AUXCTL_K;
1402129198Scognet#else
1403129198Scognet	auxctl &= ~XSCALE_AUXCTL_K;
1404129198Scognet#endif
1405171618Scognet#ifdef CPU_XSCALE_CORE3
1406171618Scognet	auxctl |= XSCALE_AUXCTL_LLR;
1407171618Scognet	auxctl |= XSCALE_AUXCTL_MD_MASK;
1408171618Scognet#endif
1409129198Scognet	__asm __volatile("mcr p15, 0, %0, c1, c0, 1"
1410129198Scognet		: : "r" (auxctl));
1411129198Scognet}
1412280847Sandrew#endif	/* CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425
1413161592Scognet	   CPU_XSCALE_80219 */
1414