cpufunc.c revision 280824
1132718Skan/*	$NetBSD: cpufunc.c,v 1.65 2003/11/05 12:53:15 scw Exp $	*/
290075Sobrien
3169689Skan/*-
490075Sobrien * arm9 support code Copyright (C) 2001 ARM Ltd
5169689Skan * Copyright (c) 1997 Mark Brinicombe.
690075Sobrien * Copyright (c) 1997 Causality Limited
7132718Skan * All rights reserved.
890075Sobrien *
990075Sobrien * Redistribution and use in source and binary forms, with or without
1090075Sobrien * modification, are permitted provided that the following conditions
1190075Sobrien * are met:
1290075Sobrien * 1. Redistributions of source code must retain the above copyright
1390075Sobrien *    notice, this list of conditions and the following disclaimer.
1490075Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1590075Sobrien *    notice, this list of conditions and the following disclaimer in the
1690075Sobrien *    documentation and/or other materials provided with the distribution.
1790075Sobrien * 3. All advertising materials mentioning features or use of this software
1890075Sobrien *    must display the following acknowledgement:
1990075Sobrien *	This product includes software developed by Causality Limited.
2090075Sobrien * 4. The name of Causality Limited may not be used to endorse or promote
21169689Skan *    products derived from this software without specific prior written
22169689Skan *    permission.
2390075Sobrien *
2490075Sobrien * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
25132718Skan * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26132718Skan * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27132718Skan * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
2890075Sobrien * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2990075Sobrien * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
3090075Sobrien * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3290075Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3390075Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3490075Sobrien * SUCH DAMAGE.
3590075Sobrien *
3690075Sobrien * RiscBSD kernel project
3790075Sobrien *
38117395Skan * cpufuncs.c
39132718Skan *
4090075Sobrien * C functions for supporting CPU / MMU / TLB specific operations.
4190075Sobrien *
4290075Sobrien * Created      : 30/01/97
4390075Sobrien */
4490075Sobrien#include <sys/cdefs.h>
4590075Sobrien__FBSDID("$FreeBSD: head/sys/arm/arm/cpufunc.c 280824 2015-03-29 21:12:59Z andrew $");
4690075Sobrien
4790075Sobrien#include <sys/param.h>
4890075Sobrien#include <sys/systm.h>
4990075Sobrien#include <sys/lock.h>
5090075Sobrien#include <sys/mutex.h>
5190075Sobrien#include <sys/bus.h>
5290075Sobrien#include <machine/bus.h>
5390075Sobrien#include <machine/cpu.h>
5490075Sobrien#include <machine/disassem.h>
5590075Sobrien
5690075Sobrien#include <vm/vm.h>
5790075Sobrien#include <vm/pmap.h>
5890075Sobrien#include <vm/uma.h>
5990075Sobrien
6090075Sobrien#include <machine/cpuconf.h>
6190075Sobrien#include <machine/cpufunc.h>
6290075Sobrien
6390075Sobrien#ifdef CPU_XSCALE_80200
6490075Sobrien#include <arm/xscale/i80200/i80200reg.h>
6590075Sobrien#include <arm/xscale/i80200/i80200var.h>
6690075Sobrien#endif
6790075Sobrien
6890075Sobrien#if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219)
6990075Sobrien#include <arm/xscale/i80321/i80321reg.h>
7090075Sobrien#include <arm/xscale/i80321/i80321var.h>
7190075Sobrien#endif
7290075Sobrien
7390075Sobrien/*
7490075Sobrien * Some definitions in i81342reg.h clash with i80321reg.h.
7590075Sobrien * This only happens for the LINT kernel. As it happens,
7690075Sobrien * we don't need anything from i81342reg.h that we already
7790075Sobrien * got from somewhere else during a LINT compile.
7890075Sobrien */
7990075Sobrien#if defined(CPU_XSCALE_81342) && !defined(COMPILING_LINT)
8090075Sobrien#include <arm/xscale/i8134x/i81342reg.h>
8190075Sobrien#endif
8290075Sobrien
8390075Sobrien#ifdef CPU_XSCALE_IXP425
8490075Sobrien#include <arm/xscale/ixp425/ixp425reg.h>
8590075Sobrien#include <arm/xscale/ixp425/ixp425var.h>
8690075Sobrien#endif
8790075Sobrien
8890075Sobrien/* PRIMARY CACHE VARIABLES */
8990075Sobrienint	arm_picache_size;
9090075Sobrienint	arm_picache_line_size;
9190075Sobrienint	arm_picache_ways;
92117395Skan
9390075Sobrienint	arm_pdcache_size;	/* and unified */
9490075Sobrienint	arm_pdcache_line_size;
9590075Sobrienint	arm_pdcache_ways;
9690075Sobrien
9790075Sobrienint	arm_pcache_type;
9890075Sobrienint	arm_pcache_unified;
9990075Sobrien
10090075Sobrienint	arm_dcache_align;
10190075Sobrienint	arm_dcache_align_mask;
10290075Sobrien
10390075Sobrienu_int	arm_cache_level;
10490075Sobrienu_int	arm_cache_type[14];
10590075Sobrienu_int	arm_cache_loc;
10690075Sobrien
107169689Skan/* 1 == use cpu_sleep(), 0 == don't */
108169689Skanint cpu_do_powersave;
109169689Skanint ctrl;
110169689Skan
111169689Skan#ifdef CPU_ARM9
112169689Skanstruct cpu_functions arm9_cpufuncs = {
113169689Skan	/* CPU functions */
114169689Skan
115169689Skan	cpufunc_id,			/* id			*/
116169689Skan	cpufunc_nullop,			/* cpwait		*/
117169689Skan
118169689Skan	/* MMU functions */
11990075Sobrien
12090075Sobrien	cpufunc_control,		/* control		*/
12190075Sobrien	cpufunc_domains,		/* Domain		*/
12290075Sobrien	arm9_setttb,			/* Setttb		*/
123169689Skan	cpufunc_faultstatus,		/* Faultstatus		*/
124169689Skan	cpufunc_faultaddress,		/* Faultaddress		*/
125169689Skan
126169689Skan	/* TLB functions */
12790075Sobrien
12890075Sobrien	armv4_tlb_flushID,		/* tlb_flushID		*/
12990075Sobrien	arm9_tlb_flushID_SE,		/* tlb_flushID_SE	*/
13090075Sobrien	armv4_tlb_flushI,		/* tlb_flushI		*/
13190075Sobrien	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
13290075Sobrien	armv4_tlb_flushD,		/* tlb_flushD		*/
13390075Sobrien	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
13490075Sobrien
13590075Sobrien	/* Cache operations */
13690075Sobrien
13790075Sobrien	arm9_icache_sync_all,		/* icache_sync_all	*/
13890075Sobrien	arm9_icache_sync_range,		/* icache_sync_range	*/
13990075Sobrien
14090075Sobrien	arm9_dcache_wbinv_all,		/* dcache_wbinv_all	*/
14190075Sobrien	arm9_dcache_wbinv_range,	/* dcache_wbinv_range	*/
14290075Sobrien	arm9_dcache_inv_range,		/* dcache_inv_range	*/
14390075Sobrien	arm9_dcache_wb_range,		/* dcache_wb_range	*/
14490075Sobrien
14590075Sobrien	armv4_idcache_inv_all,		/* idcache_inv_all	*/
14690075Sobrien	arm9_idcache_wbinv_all,		/* idcache_wbinv_all	*/
14790075Sobrien	arm9_idcache_wbinv_range,	/* idcache_wbinv_range	*/
148132718Skan	cpufunc_nullop,			/* l2cache_wbinv_all	*/
149132718Skan	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
150132718Skan	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
151132718Skan	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
152132718Skan	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
153132718Skan
154132718Skan	/* Other functions */
155132718Skan
156132718Skan	cpufunc_nullop,			/* flush_prefetchbuf	*/
157132718Skan	armv4_drain_writebuf,		/* drain_writebuf	*/
158132718Skan	cpufunc_nullop,			/* flush_brnchtgt_C	*/
159132718Skan	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
160132718Skan
161132718Skan	(void *)cpufunc_nullop,		/* sleep		*/
162132718Skan
163132718Skan	/* Soft functions */
164132718Skan
165132718Skan	cpufunc_null_fixup,		/* dataabt_fixup	*/
16690075Sobrien	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
167132718Skan
168132718Skan	arm9_context_switch,		/* context_switch	*/
169132718Skan
170132718Skan	arm9_setup			/* cpu setup		*/
171132718Skan
172132718Skan};
173132718Skan#endif /* CPU_ARM9 */
174132718Skan
175132718Skan#if defined(CPU_ARM9E)
176132718Skanstruct cpu_functions armv5_ec_cpufuncs = {
177132718Skan	/* CPU functions */
178132718Skan
179132718Skan	cpufunc_id,			/* id			*/
180132718Skan	cpufunc_nullop,			/* cpwait		*/
181132718Skan
182132718Skan	/* MMU functions */
183132718Skan
184132718Skan	cpufunc_control,		/* control		*/
18590075Sobrien	cpufunc_domains,		/* Domain		*/
18690075Sobrien	armv5_ec_setttb,		/* Setttb		*/
18790075Sobrien	cpufunc_faultstatus,		/* Faultstatus		*/
188117395Skan	cpufunc_faultaddress,		/* Faultaddress		*/
18990075Sobrien
19090075Sobrien	/* TLB functions */
19190075Sobrien
19290075Sobrien	armv4_tlb_flushID,		/* tlb_flushID		*/
19390075Sobrien	arm10_tlb_flushID_SE,		/* tlb_flushID_SE	*/
19490075Sobrien	armv4_tlb_flushI,		/* tlb_flushI		*/
19590075Sobrien	arm10_tlb_flushI_SE,		/* tlb_flushI_SE	*/
19690075Sobrien	armv4_tlb_flushD,		/* tlb_flushD		*/
19790075Sobrien	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
19890075Sobrien
19990075Sobrien	/* Cache operations */
200117395Skan
201117395Skan	armv5_ec_icache_sync_all,	/* icache_sync_all	*/
202117395Skan	armv5_ec_icache_sync_range,	/* icache_sync_range	*/
203117395Skan
20490075Sobrien	armv5_ec_dcache_wbinv_all,	/* dcache_wbinv_all	*/
20590075Sobrien	armv5_ec_dcache_wbinv_range,	/* dcache_wbinv_range	*/
206169689Skan	armv5_ec_dcache_inv_range,	/* dcache_inv_range	*/
207169689Skan	armv5_ec_dcache_wb_range,	/* dcache_wb_range	*/
208169689Skan
20990075Sobrien	armv4_idcache_inv_all,		/* idcache_inv_all	*/
210169689Skan	armv5_ec_idcache_wbinv_all,	/* idcache_wbinv_all	*/
211169689Skan	armv5_ec_idcache_wbinv_range,	/* idcache_wbinv_range	*/
212169689Skan
213169689Skan	cpufunc_nullop,                 /* l2cache_wbinv_all    */
214169689Skan	(void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
21590075Sobrien      	(void *)cpufunc_nullop,         /* l2cache_inv_range    */
21690075Sobrien	(void *)cpufunc_nullop,         /* l2cache_wb_range     */
21790075Sobrien	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
21890075Sobrien
21990075Sobrien	/* Other functions */
22090075Sobrien
22190075Sobrien	cpufunc_nullop,			/* flush_prefetchbuf	*/
22290075Sobrien	armv4_drain_writebuf,		/* drain_writebuf	*/
22390075Sobrien	cpufunc_nullop,			/* flush_brnchtgt_C	*/
22490075Sobrien	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
22590075Sobrien
22690075Sobrien	(void *)cpufunc_nullop,		/* sleep		*/
22790075Sobrien
22890075Sobrien	/* Soft functions */
22990075Sobrien
23090075Sobrien	cpufunc_null_fixup,		/* dataabt_fixup	*/
23190075Sobrien	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
23290075Sobrien
23390075Sobrien	arm10_context_switch,		/* context_switch	*/
23490075Sobrien
23590075Sobrien	arm10_setup			/* cpu setup		*/
23690075Sobrien
23790075Sobrien};
23890075Sobrien
23990075Sobrienstruct cpu_functions sheeva_cpufuncs = {
24090075Sobrien	/* CPU functions */
24190075Sobrien
24290075Sobrien	cpufunc_id,			/* id			*/
24390075Sobrien	cpufunc_nullop,			/* cpwait		*/
24490075Sobrien
24590075Sobrien	/* MMU functions */
24690075Sobrien
24790075Sobrien	cpufunc_control,		/* control		*/
24890075Sobrien	cpufunc_domains,		/* Domain		*/
24990075Sobrien	sheeva_setttb,			/* Setttb		*/
25090075Sobrien	cpufunc_faultstatus,		/* Faultstatus		*/
25190075Sobrien	cpufunc_faultaddress,		/* Faultaddress		*/
25290075Sobrien
25390075Sobrien	/* TLB functions */
25490075Sobrien
25590075Sobrien	armv4_tlb_flushID,		/* tlb_flushID		*/
25690075Sobrien	arm10_tlb_flushID_SE,		/* tlb_flushID_SE	*/
25790075Sobrien	armv4_tlb_flushI,		/* tlb_flushI		*/
25890075Sobrien	arm10_tlb_flushI_SE,		/* tlb_flushI_SE	*/
25990075Sobrien	armv4_tlb_flushD,		/* tlb_flushD		*/
26090075Sobrien	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
26190075Sobrien
26290075Sobrien	/* Cache operations */
26390075Sobrien
26490075Sobrien	armv5_ec_icache_sync_all,	/* icache_sync_all	*/
26590075Sobrien	armv5_ec_icache_sync_range,	/* icache_sync_range	*/
26690075Sobrien
26790075Sobrien	armv5_ec_dcache_wbinv_all,	/* dcache_wbinv_all	*/
26890075Sobrien	sheeva_dcache_wbinv_range,	/* dcache_wbinv_range	*/
26990075Sobrien	sheeva_dcache_inv_range,	/* dcache_inv_range	*/
27090075Sobrien	sheeva_dcache_wb_range,		/* dcache_wb_range	*/
27190075Sobrien
27290075Sobrien	armv4_idcache_inv_all,		/* idcache_inv_all	*/
27390075Sobrien	armv5_ec_idcache_wbinv_all,	/* idcache_wbinv_all	*/
27490075Sobrien	sheeva_idcache_wbinv_range,	/* idcache_wbinv_all	*/
27590075Sobrien
27690075Sobrien	sheeva_l2cache_wbinv_all,	/* l2cache_wbinv_all    */
27790075Sobrien	sheeva_l2cache_wbinv_range,	/* l2cache_wbinv_range  */
27890075Sobrien	sheeva_l2cache_inv_range,	/* l2cache_inv_range    */
27990075Sobrien	sheeva_l2cache_wb_range,	/* l2cache_wb_range     */
28090075Sobrien	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
28190075Sobrien
28290075Sobrien	/* Other functions */
28390075Sobrien
28490075Sobrien	cpufunc_nullop,			/* flush_prefetchbuf	*/
28590075Sobrien	armv4_drain_writebuf,		/* drain_writebuf	*/
28690075Sobrien	cpufunc_nullop,			/* flush_brnchtgt_C	*/
28790075Sobrien	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
28890075Sobrien
28990075Sobrien	sheeva_cpu_sleep,		/* sleep		*/
29090075Sobrien
29190075Sobrien	/* Soft functions */
29290075Sobrien
29390075Sobrien	cpufunc_null_fixup,		/* dataabt_fixup	*/
29490075Sobrien	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
29590075Sobrien
29690075Sobrien	arm10_context_switch,		/* context_switch	*/
29790075Sobrien
29890075Sobrien	arm10_setup			/* cpu setup		*/
29990075Sobrien};
30090075Sobrien#endif /* CPU_ARM9E */
30190075Sobrien
30290075Sobrien#ifdef CPU_MV_PJ4B
30390075Sobrienstruct cpu_functions pj4bv7_cpufuncs = {
30490075Sobrien	/* CPU functions */
30590075Sobrien
30690075Sobrien	cpufunc_id,			/* id			*/
30790075Sobrien	armv7_drain_writebuf,		/* cpwait		*/
30890075Sobrien
30990075Sobrien	/* MMU functions */
31090075Sobrien
31190075Sobrien	cpufunc_control,		/* control		*/
31290075Sobrien	cpufunc_domains,		/* Domain		*/
31390075Sobrien	armv7_setttb,			/* Setttb		*/
31490075Sobrien	cpufunc_faultstatus,		/* Faultstatus		*/
31590075Sobrien	cpufunc_faultaddress,		/* Faultaddress		*/
31690075Sobrien
31790075Sobrien	/* TLB functions */
31890075Sobrien
31990075Sobrien	armv7_tlb_flushID,		/* tlb_flushID		*/
32090075Sobrien	armv7_tlb_flushID_SE,		/* tlb_flushID_SE	*/
32190075Sobrien	armv7_tlb_flushID,		/* tlb_flushI		*/
32290075Sobrien	armv7_tlb_flushID_SE,		/* tlb_flushI_SE	*/
32390075Sobrien	armv7_tlb_flushID,		/* tlb_flushD		*/
32490075Sobrien	armv7_tlb_flushID_SE,		/* tlb_flushD_SE	*/
32590075Sobrien
32690075Sobrien	/* Cache operations */
32790075Sobrien	armv7_idcache_wbinv_all,	/* icache_sync_all	*/
32890075Sobrien	armv7_icache_sync_range,	/* icache_sync_range	*/
32990075Sobrien
33090075Sobrien	armv7_dcache_wbinv_all,		/* dcache_wbinv_all	*/
33190075Sobrien	armv7_dcache_wbinv_range,	/* dcache_wbinv_range	*/
33290075Sobrien	armv7_dcache_inv_range,		/* dcache_inv_range	*/
33390075Sobrien	armv7_dcache_wb_range,		/* dcache_wb_range	*/
33490075Sobrien
33590075Sobrien	armv7_idcache_inv_all,		/* idcache_inv_all	*/
33690075Sobrien	armv7_idcache_wbinv_all,	/* idcache_wbinv_all	*/
33790075Sobrien	armv7_idcache_wbinv_range,	/* idcache_wbinv_all	*/
33890075Sobrien
33990075Sobrien	(void *)cpufunc_nullop,		/* l2cache_wbinv_all	*/
34090075Sobrien	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
34190075Sobrien	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
34290075Sobrien	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
34390075Sobrien	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
34490075Sobrien
34590075Sobrien	/* Other functions */
34690075Sobrien
34790075Sobrien	cpufunc_nullop,			/* flush_prefetchbuf	*/
34890075Sobrien	armv7_drain_writebuf,		/* drain_writebuf	*/
34990075Sobrien	cpufunc_nullop,			/* flush_brnchtgt_C	*/
35090075Sobrien	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
35190075Sobrien
35290075Sobrien	(void *)cpufunc_nullop,		/* sleep		*/
35390075Sobrien
35490075Sobrien	/* Soft functions */
35590075Sobrien
35690075Sobrien	cpufunc_null_fixup,		/* dataabt_fixup	*/
35790075Sobrien	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
35890075Sobrien
35990075Sobrien	armv7_context_switch,		/* context_switch	*/
36090075Sobrien
36190075Sobrien	pj4bv7_setup			/* cpu setup		*/
36290075Sobrien};
36390075Sobrien#endif /* CPU_MV_PJ4B */
36490075Sobrien
36590075Sobrien#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
36690075Sobrien  defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
36790075Sobrien  defined(CPU_XSCALE_80219)
36890075Sobrien
36990075Sobrienstruct cpu_functions xscale_cpufuncs = {
37090075Sobrien	/* CPU functions */
37190075Sobrien
37290075Sobrien	cpufunc_id,			/* id			*/
37390075Sobrien	xscale_cpwait,			/* cpwait		*/
37490075Sobrien
37590075Sobrien	/* MMU functions */
37690075Sobrien
377132718Skan	xscale_control,			/* control		*/
37890075Sobrien	cpufunc_domains,		/* domain		*/
37990075Sobrien	xscale_setttb,			/* setttb		*/
38090075Sobrien	cpufunc_faultstatus,		/* faultstatus		*/
38190075Sobrien	cpufunc_faultaddress,		/* faultaddress		*/
38290075Sobrien
38390075Sobrien	/* TLB functions */
38490075Sobrien
38590075Sobrien	armv4_tlb_flushID,		/* tlb_flushID		*/
38690075Sobrien	xscale_tlb_flushID_SE,		/* tlb_flushID_SE	*/
38790075Sobrien	armv4_tlb_flushI,		/* tlb_flushI		*/
38890075Sobrien	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
38990075Sobrien	armv4_tlb_flushD,		/* tlb_flushD		*/
39090075Sobrien	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
39190075Sobrien
39290075Sobrien	/* Cache operations */
39390075Sobrien
39490075Sobrien	xscale_cache_syncI,		/* icache_sync_all	*/
39590075Sobrien	xscale_cache_syncI_rng,		/* icache_sync_range	*/
39690075Sobrien
39790075Sobrien	xscale_cache_purgeD,		/* dcache_wbinv_all	*/
39890075Sobrien	xscale_cache_purgeD_rng,	/* dcache_wbinv_range	*/
39990075Sobrien	xscale_cache_flushD_rng,	/* dcache_inv_range	*/
40090075Sobrien	xscale_cache_cleanD_rng,	/* dcache_wb_range	*/
40190075Sobrien
40290075Sobrien	xscale_cache_flushID,		/* idcache_inv_all	*/
40390075Sobrien	xscale_cache_purgeID,		/* idcache_wbinv_all	*/
40490075Sobrien	xscale_cache_purgeID_rng,	/* idcache_wbinv_range	*/
40590075Sobrien	cpufunc_nullop,			/* l2cache_wbinv_all 	*/
406132718Skan	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
40790075Sobrien	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
40890075Sobrien	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
40990075Sobrien	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
41090075Sobrien
41190075Sobrien	/* Other functions */
41290075Sobrien
41390075Sobrien	cpufunc_nullop,			/* flush_prefetchbuf	*/
41490075Sobrien	armv4_drain_writebuf,		/* drain_writebuf	*/
41590075Sobrien	cpufunc_nullop,			/* flush_brnchtgt_C	*/
41690075Sobrien	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
41790075Sobrien
41890075Sobrien	xscale_cpu_sleep,		/* sleep		*/
41990075Sobrien
42090075Sobrien	/* Soft functions */
42190075Sobrien
42290075Sobrien	cpufunc_null_fixup,		/* dataabt_fixup	*/
42390075Sobrien	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
42490075Sobrien
42590075Sobrien	xscale_context_switch,		/* context_switch	*/
42690075Sobrien
427132718Skan	xscale_setup			/* cpu setup		*/
42890075Sobrien};
42990075Sobrien#endif
43090075Sobrien/* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425
43190075Sobrien   CPU_XSCALE_80219 */
432169689Skan
43390075Sobrien#ifdef CPU_XSCALE_81342
43490075Sobrienstruct cpu_functions xscalec3_cpufuncs = {
43590075Sobrien	/* CPU functions */
43690075Sobrien
437169689Skan	cpufunc_id,			/* id			*/
438169689Skan	xscale_cpwait,			/* cpwait		*/
43990075Sobrien
44090075Sobrien	/* MMU functions */
44190075Sobrien
44290075Sobrien	xscale_control,			/* control		*/
44390075Sobrien	cpufunc_domains,		/* domain		*/
44490075Sobrien	xscalec3_setttb,		/* setttb		*/
44590075Sobrien	cpufunc_faultstatus,		/* faultstatus		*/
44690075Sobrien	cpufunc_faultaddress,		/* faultaddress		*/
44790075Sobrien
44890075Sobrien	/* TLB functions */
44990075Sobrien
45090075Sobrien	armv4_tlb_flushID,		/* tlb_flushID		*/
45190075Sobrien	xscale_tlb_flushID_SE,		/* tlb_flushID_SE	*/
45290075Sobrien	armv4_tlb_flushI,		/* tlb_flushI		*/
45390075Sobrien	(void *)armv4_tlb_flushI,	/* tlb_flushI_SE	*/
45490075Sobrien	armv4_tlb_flushD,		/* tlb_flushD		*/
45590075Sobrien	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
45690075Sobrien
45790075Sobrien	/* Cache operations */
45890075Sobrien
45990075Sobrien	xscalec3_cache_syncI,		/* icache_sync_all	*/
46090075Sobrien	xscalec3_cache_syncI_rng,	/* icache_sync_range	*/
46190075Sobrien
46290075Sobrien	xscalec3_cache_purgeD,		/* dcache_wbinv_all	*/
46390075Sobrien	xscalec3_cache_purgeD_rng,	/* dcache_wbinv_range	*/
464117395Skan	xscale_cache_flushD_rng,	/* dcache_inv_range	*/
46590075Sobrien	xscalec3_cache_cleanD_rng,	/* dcache_wb_range	*/
46690075Sobrien
46790075Sobrien	xscale_cache_flushID,		/* idcache_inv_all	*/
46890075Sobrien	xscalec3_cache_purgeID,		/* idcache_wbinv_all	*/
46990075Sobrien	xscalec3_cache_purgeID_rng,	/* idcache_wbinv_range	*/
47090075Sobrien	xscalec3_l2cache_purge,		/* l2cache_wbinv_all	*/
47190075Sobrien	xscalec3_l2cache_purge_rng,	/* l2cache_wbinv_range	*/
47290075Sobrien	xscalec3_l2cache_flush_rng,	/* l2cache_inv_range	*/
47390075Sobrien	xscalec3_l2cache_clean_rng,	/* l2cache_wb_range	*/
47490075Sobrien	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
47590075Sobrien
47690075Sobrien	/* Other functions */
47790075Sobrien
47890075Sobrien	cpufunc_nullop,			/* flush_prefetchbuf	*/
47990075Sobrien	armv4_drain_writebuf,		/* drain_writebuf	*/
48090075Sobrien	cpufunc_nullop,			/* flush_brnchtgt_C	*/
48190075Sobrien	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
48290075Sobrien
48390075Sobrien	xscale_cpu_sleep,		/* sleep		*/
48490075Sobrien
48590075Sobrien	/* Soft functions */
48690075Sobrien
48790075Sobrien	cpufunc_null_fixup,		/* dataabt_fixup	*/
48890075Sobrien	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
48990075Sobrien
49090075Sobrien	xscalec3_context_switch,	/* context_switch	*/
49190075Sobrien
49290075Sobrien	xscale_setup			/* cpu setup		*/
49390075Sobrien};
49490075Sobrien#endif /* CPU_XSCALE_81342 */
49590075Sobrien
49690075Sobrien
49790075Sobrien#if defined(CPU_FA526) || defined(CPU_FA626TE)
49890075Sobrienstruct cpu_functions fa526_cpufuncs = {
49990075Sobrien	/* CPU functions */
50090075Sobrien
50190075Sobrien	cpufunc_id,			/* id			*/
50290075Sobrien	cpufunc_nullop,			/* cpwait		*/
50390075Sobrien
50490075Sobrien	/* MMU functions */
50590075Sobrien
50690075Sobrien	cpufunc_control,		/* control		*/
50790075Sobrien	cpufunc_domains,		/* domain		*/
50890075Sobrien	fa526_setttb,			/* setttb		*/
50990075Sobrien	cpufunc_faultstatus,		/* faultstatus		*/
51090075Sobrien	cpufunc_faultaddress,		/* faultaddress		*/
51190075Sobrien
51290075Sobrien	/* TLB functions */
51390075Sobrien
51490075Sobrien	armv4_tlb_flushID,		/* tlb_flushID		*/
51590075Sobrien	fa526_tlb_flushID_SE,		/* tlb_flushID_SE	*/
51690075Sobrien	armv4_tlb_flushI,		/* tlb_flushI		*/
51790075Sobrien	fa526_tlb_flushI_SE,		/* tlb_flushI_SE	*/
51890075Sobrien	armv4_tlb_flushD,		/* tlb_flushD		*/
51990075Sobrien	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
52090075Sobrien
52190075Sobrien	/* Cache operations */
52290075Sobrien
52390075Sobrien	fa526_icache_sync_all,		/* icache_sync_all	*/
52490075Sobrien	fa526_icache_sync_range,	/* icache_sync_range	*/
52590075Sobrien
52690075Sobrien	fa526_dcache_wbinv_all,		/* dcache_wbinv_all	*/
52790075Sobrien	fa526_dcache_wbinv_range,	/* dcache_wbinv_range	*/
52890075Sobrien	fa526_dcache_inv_range,		/* dcache_inv_range	*/
52990075Sobrien	fa526_dcache_wb_range,		/* dcache_wb_range	*/
53090075Sobrien
53190075Sobrien	armv4_idcache_inv_all,		/* idcache_inv_all	*/
53290075Sobrien	fa526_idcache_wbinv_all,	/* idcache_wbinv_all	*/
53390075Sobrien	fa526_idcache_wbinv_range,	/* idcache_wbinv_range	*/
53490075Sobrien	cpufunc_nullop,			/* l2cache_wbinv_all	*/
53590075Sobrien	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
53690075Sobrien	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
53790075Sobrien	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
53890075Sobrien	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
53990075Sobrien
54090075Sobrien	/* Other functions */
54190075Sobrien
54290075Sobrien	fa526_flush_prefetchbuf,	/* flush_prefetchbuf	*/
54390075Sobrien	armv4_drain_writebuf,		/* drain_writebuf	*/
54490075Sobrien	cpufunc_nullop,			/* flush_brnchtgt_C	*/
54590075Sobrien	fa526_flush_brnchtgt_E,		/* flush_brnchtgt_E	*/
54690075Sobrien
54790075Sobrien	fa526_cpu_sleep,		/* sleep		*/
54890075Sobrien
54990075Sobrien	/* Soft functions */
550117395Skan
55190075Sobrien	cpufunc_null_fixup,		/* dataabt_fixup	*/
55290075Sobrien	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
553132718Skan
55490075Sobrien	fa526_context_switch,		/* context_switch	*/
55590075Sobrien
55690075Sobrien	fa526_setup			/* cpu setup 		*/
55790075Sobrien};
55890075Sobrien#endif	/* CPU_FA526 || CPU_FA626TE */
55990075Sobrien
56090075Sobrien#if defined(CPU_ARM1176)
56190075Sobrienstruct cpu_functions arm1176_cpufuncs = {
56290075Sobrien	/* CPU functions */
56390075Sobrien
56490075Sobrien	cpufunc_id,                     /* id                   */
56590075Sobrien	cpufunc_nullop,                 /* cpwait               */
56690075Sobrien
56790075Sobrien	/* MMU functions */
56890075Sobrien
56990075Sobrien	cpufunc_control,                /* control              */
57090075Sobrien	cpufunc_domains,                /* Domain               */
57190075Sobrien	arm11x6_setttb,                 /* Setttb               */
57290075Sobrien	cpufunc_faultstatus,            /* Faultstatus          */
57390075Sobrien	cpufunc_faultaddress,           /* Faultaddress         */
57490075Sobrien
57590075Sobrien	/* TLB functions */
57690075Sobrien
57790075Sobrien	arm11_tlb_flushID,              /* tlb_flushID          */
57890075Sobrien	arm11_tlb_flushID_SE,           /* tlb_flushID_SE       */
579117395Skan	arm11_tlb_flushI,               /* tlb_flushI           */
58090075Sobrien	arm11_tlb_flushI_SE,            /* tlb_flushI_SE        */
58190075Sobrien	arm11_tlb_flushD,               /* tlb_flushD           */
582132718Skan	arm11_tlb_flushD_SE,            /* tlb_flushD_SE        */
58390075Sobrien
58490075Sobrien	/* Cache operations */
58590075Sobrien
58690075Sobrien	arm11x6_icache_sync_all,        /* icache_sync_all      */
58790075Sobrien	arm11x6_icache_sync_range,      /* icache_sync_range    */
58890075Sobrien
58990075Sobrien	arm11x6_dcache_wbinv_all,       /* dcache_wbinv_all     */
59090075Sobrien	armv6_dcache_wbinv_range,       /* dcache_wbinv_range   */
59190075Sobrien	armv6_dcache_inv_range,         /* dcache_inv_range     */
59290075Sobrien	armv6_dcache_wb_range,          /* dcache_wb_range      */
59390075Sobrien
59490075Sobrien	armv6_idcache_inv_all,		/* idcache_inv_all	*/
59590075Sobrien	arm11x6_idcache_wbinv_all,      /* idcache_wbinv_all    */
59690075Sobrien	arm11x6_idcache_wbinv_range,    /* idcache_wbinv_range  */
597117395Skan
59890075Sobrien	(void *)cpufunc_nullop,         /* l2cache_wbinv_all    */
59990075Sobrien	(void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
600132718Skan	(void *)cpufunc_nullop,         /* l2cache_inv_range    */
60190075Sobrien	(void *)cpufunc_nullop,         /* l2cache_wb_range     */
60290075Sobrien	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
60390075Sobrien
60490075Sobrien	/* Other functions */
60590075Sobrien
60690075Sobrien	arm11x6_flush_prefetchbuf,      /* flush_prefetchbuf    */
60790075Sobrien	arm11_drain_writebuf,           /* drain_writebuf       */
60890075Sobrien	cpufunc_nullop,                 /* flush_brnchtgt_C     */
60990075Sobrien	(void *)cpufunc_nullop,         /* flush_brnchtgt_E     */
61090075Sobrien
61190075Sobrien	arm11x6_sleep,                  /* sleep                */
61290075Sobrien
61390075Sobrien	/* Soft functions */
61490075Sobrien
615117395Skan	cpufunc_null_fixup,             /* dataabt_fixup        */
61690075Sobrien	cpufunc_null_fixup,             /* prefetchabt_fixup    */
61790075Sobrien
618132718Skan	arm11_context_switch,           /* context_switch       */
61990075Sobrien
62090075Sobrien	arm11x6_setup                   /* cpu setup            */
62190075Sobrien};
62290075Sobrien#endif /*CPU_ARM1176 */
62390075Sobrien
62490075Sobrien#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
62590075Sobrienstruct cpu_functions cortexa_cpufuncs = {
62690075Sobrien	/* CPU functions */
62790075Sobrien
62890075Sobrien	cpufunc_id,                     /* id                   */
62990075Sobrien	cpufunc_nullop,                 /* cpwait               */
63090075Sobrien
63190075Sobrien	/* MMU functions */
632117395Skan
63390075Sobrien	cpufunc_control,                /* control              */
63490075Sobrien	cpufunc_domains,                /* Domain               */
635132718Skan	armv7_setttb,                   /* Setttb               */
63690075Sobrien	cpufunc_faultstatus,            /* Faultstatus          */
63790075Sobrien	cpufunc_faultaddress,           /* Faultaddress         */
63890075Sobrien
63990075Sobrien	/*
64090075Sobrien	 * TLB functions.  ARMv7 does all TLB ops based on a unified TLB model
64190075Sobrien	 * whether the hardware implements separate I+D or not, so we use the
64290075Sobrien	 * same 'ID' functions for all 3 variations.
64390075Sobrien	 */
644117395Skan
64590075Sobrien	armv7_tlb_flushID,              /* tlb_flushID          */
64690075Sobrien	armv7_tlb_flushID_SE,           /* tlb_flushID_SE       */
64790075Sobrien	armv7_tlb_flushID,              /* tlb_flushI           */
64890075Sobrien	armv7_tlb_flushID_SE,           /* tlb_flushI_SE        */
649117395Skan	armv7_tlb_flushID,              /* tlb_flushD           */
65090075Sobrien	armv7_tlb_flushID_SE,           /* tlb_flushD_SE        */
65190075Sobrien
652132718Skan	/* Cache operations */
653132718Skan
65490075Sobrien	armv7_icache_sync_all, 	        /* icache_sync_all      */
65590075Sobrien	armv7_icache_sync_range,        /* icache_sync_range    */
65690075Sobrien
65790075Sobrien	armv7_dcache_wbinv_all,         /* dcache_wbinv_all     */
65890075Sobrien	armv7_dcache_wbinv_range,       /* dcache_wbinv_range   */
65990075Sobrien	armv7_dcache_inv_range,         /* dcache_inv_range     */
66090075Sobrien	armv7_dcache_wb_range,          /* dcache_wb_range      */
66190075Sobrien
66290075Sobrien	armv7_idcache_inv_all,		/* idcache_inv_all	*/
66390075Sobrien	armv7_idcache_wbinv_all,        /* idcache_wbinv_all    */
66490075Sobrien	armv7_idcache_wbinv_range,      /* idcache_wbinv_range  */
66590075Sobrien
66690075Sobrien	/*
66790075Sobrien	 * Note: For CPUs using the PL310 the L2 ops are filled in when the
668117395Skan	 * L2 cache controller is actually enabled.
66990075Sobrien	 */
67090075Sobrien	cpufunc_nullop,                 /* l2cache_wbinv_all    */
671132718Skan	(void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
672132718Skan	(void *)cpufunc_nullop,         /* l2cache_inv_range    */
67390075Sobrien	(void *)cpufunc_nullop,         /* l2cache_wb_range     */
67490075Sobrien	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
67590075Sobrien
67690075Sobrien	/* Other functions */
67790075Sobrien
67890075Sobrien	cpufunc_nullop,                 /* flush_prefetchbuf    */
67990075Sobrien	armv7_drain_writebuf,           /* drain_writebuf       */
68090075Sobrien	cpufunc_nullop,                 /* flush_brnchtgt_C     */
68190075Sobrien	(void *)cpufunc_nullop,         /* flush_brnchtgt_E     */
68290075Sobrien
68390075Sobrien	armv7_sleep,                    /* sleep                */
68490075Sobrien
68590075Sobrien	/* Soft functions */
68690075Sobrien
687117395Skan	cpufunc_null_fixup,             /* dataabt_fixup        */
68890075Sobrien	cpufunc_null_fixup,             /* prefetchabt_fixup    */
68990075Sobrien
690132718Skan	armv7_context_switch,           /* context_switch       */
69190075Sobrien
69290075Sobrien	cortexa_setup                     /* cpu setup            */
69390075Sobrien};
69490075Sobrien#endif /* CPU_CORTEXA */
69590075Sobrien
69690075Sobrien/*
69790075Sobrien * Global constants also used by locore.s
69890075Sobrien */
699117395Skan
70090075Sobrienstruct cpu_functions cpufuncs;
70190075Sobrienu_int cputype;
70290075Sobrienu_int cpu_reset_needs_v4_MMU_disable;	/* flag used in locore.s */
70390075Sobrien
704117395Skan#if defined(CPU_ARM9) ||	\
70590075Sobrien  defined (CPU_ARM9E) ||	\
70690075Sobrien  defined(CPU_ARM1176) || defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) ||		\
707132718Skan  defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) ||		\
70890075Sobrien  defined(CPU_FA526) || defined(CPU_FA626TE) || defined(CPU_MV_PJ4B) ||			\
70990075Sobrien  defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \
71090075Sobrien  defined(CPU_CORTEXA) || defined(CPU_KRAIT)
71190075Sobrien
71290075Sobrien/* Global cache line sizes, use 32 as default */
71390075Sobrienint	arm_dcache_min_line_size = 32;
71490075Sobrienint	arm_icache_min_line_size = 32;
71590075Sobrienint	arm_idcache_min_line_size = 32;
71690075Sobrien
71790075Sobrienstatic void get_cachetype_cp15(void);
71890075Sobrien
71990075Sobrien/* Additional cache information local to this file.  Log2 of some of the
72090075Sobrien   above numbers.  */
72190075Sobrienstatic int	arm_dcache_l2_nsets;
72290075Sobrienstatic int	arm_dcache_l2_assoc;
72390075Sobrienstatic int	arm_dcache_l2_linesize;
72490075Sobrien
72590075Sobrienstatic void
72690075Sobrienget_cachetype_cp15()
72790075Sobrien{
72890075Sobrien	u_int ctype, isize, dsize, cpuid;
72990075Sobrien	u_int clevel, csize, i, sel;
73090075Sobrien	u_int multiplier;
73190075Sobrien	u_char type;
73290075Sobrien
73390075Sobrien	__asm __volatile("mrc p15, 0, %0, c0, c0, 1"
73490075Sobrien		: "=r" (ctype));
73590075Sobrien
73690075Sobrien	cpuid = cpufunc_id();
73790075Sobrien	/*
73890075Sobrien	 * ...and thus spake the ARM ARM:
73990075Sobrien	 *
74090075Sobrien	 * If an <opcode2> value corresponding to an unimplemented or
74190075Sobrien	 * reserved ID register is encountered, the System Control
74290075Sobrien	 * processor returns the value of the main ID register.
74390075Sobrien	 */
74490075Sobrien	if (ctype == cpuid)
74590075Sobrien		goto out;
74690075Sobrien
74790075Sobrien	if (CPU_CT_FORMAT(ctype) == CPU_CT_ARMV7) {
74890075Sobrien		/* Resolve minimal cache line sizes */
74990075Sobrien		arm_dcache_min_line_size = 1 << (CPU_CT_DMINLINE(ctype) + 2);
75090075Sobrien		arm_icache_min_line_size = 1 << (CPU_CT_IMINLINE(ctype) + 2);
75190075Sobrien		arm_idcache_min_line_size =
75290075Sobrien		    min(arm_icache_min_line_size, arm_dcache_min_line_size);
75390075Sobrien
75490075Sobrien		__asm __volatile("mrc p15, 1, %0, c0, c0, 1"
75590075Sobrien		    : "=r" (clevel));
75690075Sobrien		arm_cache_level = clevel;
75790075Sobrien		arm_cache_loc = CPU_CLIDR_LOC(arm_cache_level);
75890075Sobrien		i = 0;
75990075Sobrien		while ((type = (clevel & 0x7)) && i < 7) {
76090075Sobrien			if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
76190075Sobrien			    type == CACHE_SEP_CACHE) {
76290075Sobrien				sel = i << 1;
76390075Sobrien				__asm __volatile("mcr p15, 2, %0, c0, c0, 0"
76490075Sobrien				    : : "r" (sel));
76590075Sobrien				__asm __volatile("mrc p15, 1, %0, c0, c0, 0"
76690075Sobrien				    : "=r" (csize));
767117395Skan				arm_cache_type[sel] = csize;
76890075Sobrien				arm_dcache_align = 1 <<
76990075Sobrien				    (CPUV7_CT_xSIZE_LEN(csize) + 4);
770132718Skan				arm_dcache_align_mask = arm_dcache_align - 1;
77190075Sobrien			}
77290075Sobrien			if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
77390075Sobrien				sel = (i << 1) | 1;
77490075Sobrien				__asm __volatile("mcr p15, 2, %0, c0, c0, 0"
77590075Sobrien				    : : "r" (sel));
77690075Sobrien				__asm __volatile("mrc p15, 1, %0, c0, c0, 0"
77790075Sobrien				    : "=r" (csize));
77890075Sobrien				arm_cache_type[sel] = csize;
77990075Sobrien			}
78090075Sobrien			i++;
78190075Sobrien			clevel >>= 3;
78290075Sobrien		}
78390075Sobrien	} else {
78490075Sobrien		if ((ctype & CPU_CT_S) == 0)
78590075Sobrien			arm_pcache_unified = 1;
786117395Skan
78790075Sobrien		/*
78890075Sobrien		 * If you want to know how this code works, go read the ARM ARM.
789132718Skan		 */
79090075Sobrien
79190075Sobrien		arm_pcache_type = CPU_CT_CTYPE(ctype);
792117395Skan
79390075Sobrien		if (arm_pcache_unified == 0) {
79490075Sobrien			isize = CPU_CT_ISIZE(ctype);
79590075Sobrien			multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2;
79690075Sobrien			arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3);
79790075Sobrien			if (CPU_CT_xSIZE_ASSOC(isize) == 0) {
798169689Skan				if (isize & CPU_CT_xSIZE_M)
79990075Sobrien					arm_picache_line_size = 0; /* not present */
800169689Skan				else
80190075Sobrien					arm_picache_ways = 1;
802117395Skan			} else {
80390075Sobrien				arm_picache_ways = multiplier <<
80490075Sobrien				    (CPU_CT_xSIZE_ASSOC(isize) - 1);
80590075Sobrien			}
80690075Sobrien			arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
80790075Sobrien		}
80890075Sobrien
80990075Sobrien		dsize = CPU_CT_DSIZE(ctype);
81090075Sobrien		multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
81190075Sobrien		arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
81290075Sobrien		if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
81390075Sobrien			if (dsize & CPU_CT_xSIZE_M)
81490075Sobrien				arm_pdcache_line_size = 0; /* not present */
815117395Skan			else
81690075Sobrien				arm_pdcache_ways = 1;
81790075Sobrien		} else {
81890075Sobrien			arm_pdcache_ways = multiplier <<
81990075Sobrien			    (CPU_CT_xSIZE_ASSOC(dsize) - 1);
82090075Sobrien		}
82190075Sobrien		arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
82290075Sobrien
82390075Sobrien		arm_dcache_align = arm_pdcache_line_size;
82490075Sobrien
82590075Sobrien		arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2;
82690075Sobrien		arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3;
82790075Sobrien		arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) -
82890075Sobrien		    CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize);
82990075Sobrien
83090075Sobrien	out:
831132718Skan		arm_dcache_align_mask = arm_dcache_align - 1;
83290075Sobrien	}
83390075Sobrien}
83490075Sobrien#endif /* ARM9 || XSCALE */
83590075Sobrien
83690075Sobrien/*
83790075Sobrien * Cannot panic here as we may not have a console yet ...
83890075Sobrien */
83990075Sobrien
84090075Sobrienint
84190075Sobrienset_cpufuncs()
84290075Sobrien{
84390075Sobrien	cputype = cpufunc_id();
84490075Sobrien	cputype &= CPU_ID_CPU_MASK;
84590075Sobrien
84690075Sobrien	/*
84790075Sobrien	 * NOTE: cpu_do_powersave defaults to off.  If we encounter a
84890075Sobrien	 * CPU type where we want to use it by default, then we set it.
84990075Sobrien	 */
85090075Sobrien
85190075Sobrien#ifdef CPU_ARM9
85290075Sobrien	if (((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD ||
85390075Sobrien	     (cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_TI) &&
85490075Sobrien	    (cputype & 0x0000f000) == 0x00009000) {
85590075Sobrien		cpufuncs = arm9_cpufuncs;
85690075Sobrien		cpu_reset_needs_v4_MMU_disable = 1;	/* V4 or higher */
85790075Sobrien		get_cachetype_cp15();
85890075Sobrien		arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize;
85990075Sobrien		arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize +
86090075Sobrien		    arm_dcache_l2_nsets)) - arm9_dcache_sets_inc;
86190075Sobrien		arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc);
86290075Sobrien		arm9_dcache_index_max = 0U - arm9_dcache_index_inc;
86390075Sobrien		pmap_pte_init_generic();
86490075Sobrien		goto out;
86590075Sobrien	}
86690075Sobrien#endif /* CPU_ARM9 */
86790075Sobrien#if defined(CPU_ARM9E)
86890075Sobrien	if (cputype == CPU_ID_MV88FR131 || cputype == CPU_ID_MV88FR571_VD ||
86990075Sobrien	    cputype == CPU_ID_MV88FR571_41) {
87090075Sobrien		uint32_t sheeva_ctrl;
871169689Skan
87290075Sobrien		sheeva_ctrl = (MV_DC_STREAM_ENABLE | MV_BTB_DISABLE |
87390075Sobrien		    MV_L2_ENABLE);
87490075Sobrien		/*
87590075Sobrien		 * Workaround for Marvell MV78100 CPU: Cache prefetch
87690075Sobrien		 * mechanism may affect the cache coherency validity,
87790075Sobrien		 * so it needs to be disabled.
87890075Sobrien		 *
87990075Sobrien		 * Refer to errata document MV-S501058-00C.pdf (p. 3.1
880117395Skan		 * L2 Prefetching Mechanism) for details.
88190075Sobrien		 */
88290075Sobrien		if (cputype == CPU_ID_MV88FR571_VD ||
883132718Skan		    cputype == CPU_ID_MV88FR571_41)
88490075Sobrien			sheeva_ctrl |= MV_L2_PREFETCH_DISABLE;
88590075Sobrien
88690075Sobrien		sheeva_control_ext(0xffffffff & ~MV_WA_ENABLE, sheeva_ctrl);
88790075Sobrien
88890075Sobrien		cpufuncs = sheeva_cpufuncs;
889169689Skan		get_cachetype_cp15();
890169689Skan		pmap_pte_init_generic();
89190075Sobrien		goto out;
89290075Sobrien	} else if (cputype == CPU_ID_ARM926EJS) {
89390075Sobrien		cpufuncs = armv5_ec_cpufuncs;
89490075Sobrien		get_cachetype_cp15();
89590075Sobrien		pmap_pte_init_generic();
89690075Sobrien		goto out;
89790075Sobrien	}
89890075Sobrien#endif /* CPU_ARM9E */
89990075Sobrien#if defined(CPU_ARM1176)
90090075Sobrien	if (cputype == CPU_ID_ARM1176JZS) {
90190075Sobrien		cpu_reset_needs_v4_MMU_disable = 1;     /* V4 or higher */
90290075Sobrien		get_cachetype_cp15();
90390075Sobrien
90490075Sobrien		pmap_pte_init_mmu_v6();
905169689Skan
906169689Skan		goto out;
90790075Sobrien	}
90890075Sobrien#endif /* CPU_ARM1176 */
90990075Sobrien#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
91090075Sobrien	if (cputype == CPU_ID_CORTEXA5 ||
91190075Sobrien	    cputype == CPU_ID_CORTEXA7 ||
91290075Sobrien	    cputype == CPU_ID_CORTEXA8R1 ||
91390075Sobrien	    cputype == CPU_ID_CORTEXA8R2 ||
91490075Sobrien	    cputype == CPU_ID_CORTEXA8R3 ||
91590075Sobrien	    cputype == CPU_ID_CORTEXA9R1 ||
91690075Sobrien	    cputype == CPU_ID_CORTEXA9R2 ||
91790075Sobrien	    cputype == CPU_ID_CORTEXA9R3 ||
91890075Sobrien	    cputype == CPU_ID_CORTEXA12R0 ||
91990075Sobrien	    cputype == CPU_ID_CORTEXA15R0 ||
92090075Sobrien	    cputype == CPU_ID_CORTEXA15R1 ||
92190075Sobrien	    cputype == CPU_ID_CORTEXA15R2 ||
92290075Sobrien	    cputype == CPU_ID_CORTEXA15R3 ||
92390075Sobrien	    cputype == CPU_ID_KRAIT ) {
924117395Skan		cpufuncs = cortexa_cpufuncs;
92590075Sobrien		cpu_reset_needs_v4_MMU_disable = 1;     /* V4 or higher */
92690075Sobrien		get_cachetype_cp15();
927132718Skan
92890075Sobrien		pmap_pte_init_mmu_v6();
92990075Sobrien		/* Use powersave on this CPU. */
93090075Sobrien		cpu_do_powersave = 1;
93190075Sobrien		goto out;
93290075Sobrien	}
93390075Sobrien#endif /* CPU_CORTEXA */
93490075Sobrien
93590075Sobrien#if defined(CPU_MV_PJ4B)
93690075Sobrien	if (cputype == CPU_ID_MV88SV581X_V7 ||
93790075Sobrien	    cputype == CPU_ID_MV88SV584X_V7 ||
93890075Sobrien	    cputype == CPU_ID_ARM_88SV581X_V7) {
93990075Sobrien		cpufuncs = pj4bv7_cpufuncs;
94090075Sobrien		get_cachetype_cp15();
94190075Sobrien		pmap_pte_init_mmu_v6();
94290075Sobrien		goto out;
94390075Sobrien	}
94490075Sobrien#endif /* CPU_MV_PJ4B */
94590075Sobrien
94690075Sobrien#if defined(CPU_FA526) || defined(CPU_FA626TE)
94790075Sobrien	if (cputype == CPU_ID_FA526 || cputype == CPU_ID_FA626TE) {
94890075Sobrien		cpufuncs = fa526_cpufuncs;
94990075Sobrien		cpu_reset_needs_v4_MMU_disable = 1;	/* SA needs it	*/
95090075Sobrien		get_cachetype_cp15();
95190075Sobrien		pmap_pte_init_generic();
952132718Skan
95390075Sobrien		/* Use powersave on this CPU. */
95490075Sobrien		cpu_do_powersave = 1;
95590075Sobrien
95690075Sobrien		goto out;
95790075Sobrien	}
95890075Sobrien#endif	/* CPU_FA526 || CPU_FA626TE */
95990075Sobrien
96090075Sobrien#ifdef CPU_XSCALE_80200
96190075Sobrien	if (cputype == CPU_ID_80200) {
96290075Sobrien		int rev = cpufunc_id() & CPU_ID_REVISION_MASK;
96390075Sobrien
96490075Sobrien		i80200_icu_init();
96590075Sobrien
96690075Sobrien#if defined(XSCALE_CCLKCFG)
96790075Sobrien		/*
96890075Sobrien		 * Crank CCLKCFG to maximum legal value.
96990075Sobrien		 */
97090075Sobrien		__asm __volatile ("mcr p14, 0, %0, c6, c0, 0"
97190075Sobrien			:
97290075Sobrien			: "r" (XSCALE_CCLKCFG));
97390075Sobrien#endif
97490075Sobrien
97590075Sobrien		/*
97690075Sobrien		 * XXX Disable ECC in the Bus Controller Unit; we
97790075Sobrien		 * don't really support it, yet.  Clear any pending
97890075Sobrien		 * error indications.
97990075Sobrien		 */
98090075Sobrien		__asm __volatile("mcr p13, 0, %0, c0, c1, 0"
98190075Sobrien			:
98290075Sobrien			: "r" (BCUCTL_E0|BCUCTL_E1|BCUCTL_EV));
983117395Skan
984117395Skan		cpufuncs = xscale_cpufuncs;
98590075Sobrien		/*
98690075Sobrien		 * i80200 errata: Step-A0 and A1 have a bug where
98790075Sobrien		 * D$ dirty bits are not cleared on "invalidate by
98890075Sobrien		 * address".
98990075Sobrien		 *
99090075Sobrien		 * Workaround: Clean cache line before invalidating.
99190075Sobrien		 */
99290075Sobrien		if (rev == 0 || rev == 1)
99390075Sobrien			cpufuncs.cf_dcache_inv_range = xscale_cache_purgeD_rng;
99490075Sobrien
99590075Sobrien		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
99690075Sobrien		get_cachetype_cp15();
99790075Sobrien		pmap_pte_init_xscale();
99890075Sobrien		goto out;
99990075Sobrien	}
100090075Sobrien#endif /* CPU_XSCALE_80200 */
100190075Sobrien#if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219)
100290075Sobrien	if (cputype == CPU_ID_80321_400 || cputype == CPU_ID_80321_600 ||
100390075Sobrien	    cputype == CPU_ID_80321_400_B0 || cputype == CPU_ID_80321_600_B0 ||
100490075Sobrien	    cputype == CPU_ID_80219_400 || cputype == CPU_ID_80219_600) {
100590075Sobrien		cpufuncs = xscale_cpufuncs;
100690075Sobrien		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
100790075Sobrien		get_cachetype_cp15();
100890075Sobrien		pmap_pte_init_xscale();
100990075Sobrien		goto out;
101090075Sobrien	}
101190075Sobrien#endif /* CPU_XSCALE_80321 */
101290075Sobrien
101390075Sobrien#if defined(CPU_XSCALE_81342)
101490075Sobrien	if (cputype == CPU_ID_81342) {
101590075Sobrien		cpufuncs = xscalec3_cpufuncs;
101690075Sobrien		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
101790075Sobrien		get_cachetype_cp15();
101890075Sobrien		pmap_pte_init_xscale();
101990075Sobrien		goto out;
102090075Sobrien	}
102190075Sobrien#endif /* CPU_XSCALE_81342 */
102290075Sobrien#ifdef CPU_XSCALE_PXA2X0
102390075Sobrien	/* ignore core revision to test PXA2xx CPUs */
102490075Sobrien	if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA250 ||
102590075Sobrien	    (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X ||
102690075Sobrien	    (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA210) {
102790075Sobrien
102890075Sobrien		cpufuncs = xscale_cpufuncs;
102990075Sobrien		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
103090075Sobrien		get_cachetype_cp15();
103190075Sobrien		pmap_pte_init_xscale();
103290075Sobrien
103390075Sobrien		/* Use powersave on this CPU. */
103490075Sobrien		cpu_do_powersave = 1;
103590075Sobrien
103690075Sobrien		goto out;
103790075Sobrien	}
103890075Sobrien#endif /* CPU_XSCALE_PXA2X0 */
103990075Sobrien#ifdef CPU_XSCALE_IXP425
104090075Sobrien	if (cputype == CPU_ID_IXP425_533 || cputype == CPU_ID_IXP425_400 ||
104190075Sobrien            cputype == CPU_ID_IXP425_266 || cputype == CPU_ID_IXP435) {
104290075Sobrien
104390075Sobrien		cpufuncs = xscale_cpufuncs;
104490075Sobrien		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
104590075Sobrien		get_cachetype_cp15();
104690075Sobrien		pmap_pte_init_xscale();
104790075Sobrien
104890075Sobrien		goto out;
104990075Sobrien	}
105090075Sobrien#endif /* CPU_XSCALE_IXP425 */
105190075Sobrien	/*
105290075Sobrien	 * Bzzzz. And the answer was ...
105390075Sobrien	 */
1054117395Skan	panic("No support for this CPU type (%08x) in kernel", cputype);
105590075Sobrien	return(ARCHITECTURE_NOT_PRESENT);
105690075Sobrienout:
1057132718Skan	uma_set_align(arm_dcache_align_mask);
1058132718Skan	return (0);
105990075Sobrien}
106090075Sobrien
106190075Sobrien/*
106290075Sobrien * Fixup routines for data and prefetch aborts.
106390075Sobrien *
106490075Sobrien * Several compile time symbols are used
106590075Sobrien *
106690075Sobrien * DEBUG_FAULT_CORRECTION - Print debugging information during the
106790075Sobrien * correction of registers after a fault.
106890075Sobrien */
106990075Sobrien
107090075Sobrien
107190075Sobrien/*
107290075Sobrien * Null abort fixup routine.
107390075Sobrien * For use when no fixup is required.
107490075Sobrien */
107590075Sobrienint
107690075Sobriencpufunc_null_fixup(arg)
107790075Sobrien	void *arg;
107890075Sobrien{
107990075Sobrien	return(ABORT_FIXUP_OK);
108090075Sobrien}
108190075Sobrien
108290075Sobrien/*
108390075Sobrien * CPU Setup code
108490075Sobrien */
108590075Sobrien
108690075Sobrien#ifdef CPU_ARM9
108790075Sobrienvoid
108890075Sobrienarm9_setup(void)
108990075Sobrien{
109090075Sobrien	int cpuctrl, cpuctrlmask;
109190075Sobrien
109290075Sobrien	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
109390075Sobrien	    | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
109490075Sobrien	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
109590075Sobrien	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE |
109690075Sobrien	    CPU_CONTROL_ROUNDROBIN;
109790075Sobrien	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
109890075Sobrien		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
109990075Sobrien		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
110090075Sobrien		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
110190075Sobrien		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
110290075Sobrien		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_VECRELOC
110390075Sobrien		 | CPU_CONTROL_ROUNDROBIN;
110490075Sobrien
110590075Sobrien#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
110690075Sobrien	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
110790075Sobrien#endif
110890075Sobrien
110990075Sobrien#ifdef __ARMEB__
111090075Sobrien	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
111190075Sobrien#endif
111290075Sobrien	if (vector_page == ARM_VECTORS_HIGH)
111390075Sobrien		cpuctrl |= CPU_CONTROL_VECRELOC;
111490075Sobrien
111590075Sobrien	/* Clear out the cache */
1116117395Skan	cpu_idcache_wbinv_all();
111790075Sobrien
111890075Sobrien	/* Set the control register */
111990075Sobrien	cpu_control(cpuctrlmask, cpuctrl);
112090075Sobrien	ctrl = cpuctrl;
112190075Sobrien
112290075Sobrien}
112390075Sobrien#endif	/* CPU_ARM9 */
112490075Sobrien
112590075Sobrien#if defined(CPU_ARM9E)
112690075Sobrienvoid
112790075Sobrienarm10_setup(void)
112890075Sobrien{
112990075Sobrien	int cpuctrl, cpuctrlmask;
113090075Sobrien
113190075Sobrien	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
113290075Sobrien	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
113390075Sobrien	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE;
113490075Sobrien	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
113590075Sobrien	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1136117395Skan	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
113790075Sobrien	    | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
113890075Sobrien	    | CPU_CONTROL_BPRD_ENABLE
113990075Sobrien	    | CPU_CONTROL_ROUNDROBIN | CPU_CONTROL_CPCLK;
114090075Sobrien
114190075Sobrien#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
114290075Sobrien	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
114390075Sobrien#endif
114490075Sobrien
114590075Sobrien#ifdef __ARMEB__
114690075Sobrien	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
114790075Sobrien#endif
114890075Sobrien
114990075Sobrien	/* Clear out the cache */
115090075Sobrien	cpu_idcache_wbinv_all();
115190075Sobrien
115290075Sobrien	/* Now really make sure they are clean.  */
115390075Sobrien	__asm __volatile ("mcr\tp15, 0, r0, c7, c7, 0" : : );
115490075Sobrien
115590075Sobrien	if (vector_page == ARM_VECTORS_HIGH)
115690075Sobrien		cpuctrl |= CPU_CONTROL_VECRELOC;
115790075Sobrien
115890075Sobrien	/* Set the control register */
115990075Sobrien	ctrl = cpuctrl;
116090075Sobrien	cpu_control(0xffffffff, cpuctrl);
116190075Sobrien
116290075Sobrien	/* And again. */
116390075Sobrien	cpu_idcache_wbinv_all();
116490075Sobrien}
116590075Sobrien#endif	/* CPU_ARM9E || CPU_ARM10 */
116690075Sobrien
116790075Sobrien#if defined(CPU_ARM1176) \
116890075Sobrien || defined(CPU_MV_PJ4B) \
116990075Sobrien || defined(CPU_CORTEXA) || defined(CPU_KRAIT)
117090075Sobrienstatic __inline void
117190075Sobriencpu_scc_setup_ccnt(void)
117290075Sobrien{
117390075Sobrien/* This is how you give userland access to the CCNT and PMCn
117490075Sobrien * registers.
117590075Sobrien * BEWARE! This gives write access also, which may not be what
117690075Sobrien * you want!
117790075Sobrien */
117890075Sobrien#ifdef _PMC_USER_READ_WRITE_
117990075Sobrien#if defined(CPU_ARM1176)
118090075Sobrien	/* Use the Secure User and Non-secure Access Validation Control Register
1181117395Skan	 * to allow userland access
1182117395Skan	 */
1183117395Skan	__asm volatile ("mcr	p15, 0, %0, c15, c9, 0\n\t"
1184117395Skan			:
118590075Sobrien			: "r"(0x00000001));
1186117395Skan#else
1187117395Skan	/* Set PMUSERENR[0] to allow userland access */
118890075Sobrien	__asm volatile ("mcr	p15, 0, %0, c9, c14, 0\n\t"
1189117395Skan			:
1190117395Skan			: "r"(0x00000001));
1191117395Skan#endif
119290075Sobrien#endif
1193117395Skan#if defined(CPU_ARM1176)
1194117395Skan	/* Set PMCR[2,0] to enable counters and reset CCNT */
119590075Sobrien	__asm volatile ("mcr	p15, 0, %0, c15, c12, 0\n\t"
1196117395Skan			:
1197117395Skan			: "r"(0x00000005));
1198117395Skan#else
119990075Sobrien	/* Set up the PMCCNTR register as a cyclecounter:
1200117395Skan	 * Set PMINTENCLR to 0xFFFFFFFF to block interrupts
1201117395Skan	 * Set PMCR[2,0] to enable counters and reset CCNT
120290075Sobrien	 * Set PMCNTENSET to 0x80000000 to enable CCNT */
1203117395Skan	__asm volatile ("mcr	p15, 0, %0, c9, c14, 2\n\t"
1204117395Skan			"mcr	p15, 0, %1, c9, c12, 0\n\t"
1205117395Skan			"mcr	p15, 0, %2, c9, c12, 1\n\t"
120690075Sobrien			:
120790075Sobrien			: "r"(0xFFFFFFFF),
120890075Sobrien			  "r"(0x00000005),
1209117395Skan			  "r"(0x80000000));
121090075Sobrien#endif
121190075Sobrien}
121290075Sobrien#endif
121390075Sobrien
121490075Sobrien#if defined(CPU_ARM1176)
1215117395Skanvoid
1216117395Skanarm11x6_setup(void)
1217117395Skan{
1218117395Skan	int cpuctrl, cpuctrl_wax;
1219117395Skan	uint32_t auxctrl, auxctrl_wax;
1220117395Skan	uint32_t tmp, tmp2;
1221117395Skan	uint32_t sbz=0;
1222117395Skan	uint32_t cpuid;
1223117395Skan
1224117395Skan	cpuid = cpufunc_id();
1225117395Skan
1226117395Skan	cpuctrl =
1227117395Skan		CPU_CONTROL_MMU_ENABLE  |
1228117395Skan		CPU_CONTROL_DC_ENABLE   |
1229117395Skan		CPU_CONTROL_WBUF_ENABLE |
1230117395Skan		CPU_CONTROL_32BP_ENABLE |
1231117395Skan		CPU_CONTROL_32BD_ENABLE |
1232117395Skan		CPU_CONTROL_LABT_ENABLE |
1233117395Skan		CPU_CONTROL_SYST_ENABLE |
1234117395Skan		CPU_CONTROL_IC_ENABLE;
1235117395Skan
1236117395Skan	/*
1237117395Skan	 * "write as existing" bits
1238117395Skan	 * inverse of this is mask
1239117395Skan	 */
1240117395Skan	cpuctrl_wax =
124190075Sobrien		(3 << 30) | /* SBZ */
124290075Sobrien		(1 << 29) | /* FA */
124390075Sobrien		(1 << 28) | /* TR */
124490075Sobrien		(3 << 26) | /* SBZ */
124590075Sobrien		(3 << 19) | /* SBZ */
124690075Sobrien		(1 << 17);  /* SBZ */
1247117395Skan
124890075Sobrien	cpuctrl |= CPU_CONTROL_BPRD_ENABLE;
124990075Sobrien	cpuctrl |= CPU_CONTROL_V6_EXTPAGE;
1250132718Skan
125190075Sobrien#ifdef __ARMEB__
125290075Sobrien	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
125390075Sobrien#endif
125490075Sobrien
125590075Sobrien	if (vector_page == ARM_VECTORS_HIGH)
125690075Sobrien		cpuctrl |= CPU_CONTROL_VECRELOC;
125790075Sobrien
125890075Sobrien	auxctrl = 0;
1259117395Skan	auxctrl_wax = ~0;
126090075Sobrien
126190075Sobrien	/*
126290075Sobrien	 * Enable an errata workaround
126390075Sobrien	 */
126490075Sobrien	if ((cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM1176JZS) { /* ARM1176JZSr0 */
1265132718Skan		auxctrl = ARM1176_AUXCTL_PHD;
126690075Sobrien		auxctrl_wax = ~ARM1176_AUXCTL_PHD;
126790075Sobrien	}
126890075Sobrien
126990075Sobrien	/* Clear out the cache */
127090075Sobrien	cpu_idcache_wbinv_all();
127190075Sobrien
127290075Sobrien	/* Now really make sure they are clean.  */
127390075Sobrien	__asm volatile ("mcr\tp15, 0, %0, c7, c7, 0" : : "r"(sbz));
127490075Sobrien
1275117395Skan	/* Allow detection code to find the VFP if it's fitted.  */
127690075Sobrien	__asm volatile ("mcr\tp15, 0, %0, c1, c0, 2" : : "r" (0x0fffffff));
127790075Sobrien
127890075Sobrien	/* Set the control register */
127990075Sobrien	ctrl = cpuctrl;
128090075Sobrien	cpu_control(~cpuctrl_wax, cpuctrl);
128190075Sobrien
128290075Sobrien	__asm volatile ("mrc	p15, 0, %0, c1, c0, 1\n\t"
1283117395Skan			"and	%1, %0, %2\n\t"
1284132718Skan			"orr	%1, %1, %3\n\t"
128590075Sobrien			"teq	%0, %1\n\t"
128690075Sobrien			"mcrne	p15, 0, %1, c1, c0, 1\n\t"
128790075Sobrien			: "=r"(tmp), "=r"(tmp2) :
1288117395Skan			  "r"(auxctrl_wax), "r"(auxctrl));
1289117395Skan
1290117395Skan	/* And again. */
129190075Sobrien	cpu_idcache_wbinv_all();
129290075Sobrien
129390075Sobrien	cpu_scc_setup_ccnt();
1294117395Skan}
129590075Sobrien#endif  /* CPU_ARM1176 */
1296117395Skan
1297132718Skan#ifdef CPU_MV_PJ4B
1298117395Skanvoid
129990075Sobrienpj4bv7_setup(void)
130090075Sobrien{
130190075Sobrien	int cpuctrl;
1302117395Skan
1303117395Skan	pj4b_config();
1304117395Skan
1305132718Skan	cpuctrl = CPU_CONTROL_MMU_ENABLE;
1306117395Skan#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1307117395Skan	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1308117395Skan#endif
1309117395Skan	cpuctrl |= CPU_CONTROL_DC_ENABLE;
1310117395Skan	cpuctrl |= (0xf << 3);
131190075Sobrien	cpuctrl |= CPU_CONTROL_BPRD_ENABLE;
131290075Sobrien	cpuctrl |= CPU_CONTROL_IC_ENABLE;
131390075Sobrien	if (vector_page == ARM_VECTORS_HIGH)
131490075Sobrien		cpuctrl |= CPU_CONTROL_VECRELOC;
131590075Sobrien	cpuctrl |= (0x5 << 16) | (1 < 22);
1316132718Skan	cpuctrl |= CPU_CONTROL_V6_EXTPAGE;
131790075Sobrien
131890075Sobrien	/* Clear out the cache */
131990075Sobrien	cpu_idcache_wbinv_all();
132090075Sobrien
1321117395Skan	/* Set the control register */
132290075Sobrien	ctrl = cpuctrl;
132390075Sobrien	cpu_control(0xFFFFFFFF, cpuctrl);
132490075Sobrien
132590075Sobrien	/* And again. */
132690075Sobrien	cpu_idcache_wbinv_all();
132790075Sobrien
1328117395Skan	cpu_scc_setup_ccnt();
132990075Sobrien}
1330117395Skan#endif /* CPU_MV_PJ4B */
1331132718Skan
1332117395Skan#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
133390075Sobrien
133490075Sobrienvoid
133590075Sobriencortexa_setup(void)
133690075Sobrien{
133790075Sobrien	int cpuctrl, cpuctrlmask;
133890075Sobrien
133990075Sobrien	cpuctrlmask = CPU_CONTROL_MMU_ENABLE |     /* MMU enable         [0] */
1340132718Skan	    CPU_CONTROL_AFLT_ENABLE |    /* Alignment fault    [1] */
134190075Sobrien	    CPU_CONTROL_DC_ENABLE |      /* DCache enable      [2] */
134290075Sobrien	    CPU_CONTROL_BPRD_ENABLE |    /* Branch prediction [11] */
134390075Sobrien	    CPU_CONTROL_IC_ENABLE |      /* ICache enable     [12] */
134490075Sobrien	    CPU_CONTROL_VECRELOC;        /* Vector relocation [13] */
134590075Sobrien
1346169689Skan	cpuctrl = CPU_CONTROL_MMU_ENABLE |
134790075Sobrien	    CPU_CONTROL_IC_ENABLE |
134890075Sobrien	    CPU_CONTROL_DC_ENABLE |
134990075Sobrien	    CPU_CONTROL_BPRD_ENABLE;
135090075Sobrien
135190075Sobrien#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
135290075Sobrien	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1353132718Skan#endif
135490075Sobrien
135590075Sobrien	/* Switch to big endian */
135690075Sobrien#ifdef __ARMEB__
135790075Sobrien	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
135890075Sobrien#endif
1359169689Skan
136090075Sobrien	/* Check if the vector page is at the high address (0xffff0000) */
136190075Sobrien	if (vector_page == ARM_VECTORS_HIGH)
136290075Sobrien		cpuctrl |= CPU_CONTROL_VECRELOC;
136390075Sobrien
136490075Sobrien	/* Clear out the cache */
1365132718Skan	cpu_idcache_wbinv_all();
136690075Sobrien
136790075Sobrien	/* Set the control register */
136890075Sobrien	ctrl = cpuctrl;
136990075Sobrien	cpu_control(cpuctrlmask, cpuctrl);
137090075Sobrien
137190075Sobrien	/* And again. */
137290075Sobrien	cpu_idcache_wbinv_all();
137390075Sobrien#ifdef SMP
137490075Sobrien	armv7_auxctrl((1 << 6) | (1 << 0), (1 << 6) | (1 << 0)); /* Enable SMP + TLB broadcasting  */
137590075Sobrien#endif
137690075Sobrien
137790075Sobrien	cpu_scc_setup_ccnt();
1378132718Skan}
137990075Sobrien#endif  /* CPU_CORTEXA */
138090075Sobrien
1381169689Skan#if defined(CPU_FA526) || defined(CPU_FA626TE)
138290075Sobrienvoid
138390075Sobrienfa526_setup(void)
138490075Sobrien{
138590075Sobrien	int cpuctrl, cpuctrlmask;
138690075Sobrien
138790075Sobrien	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
138890075Sobrien		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1389169689Skan		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1390169689Skan		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
1391169689Skan		| CPU_CONTROL_BPRD_ENABLE;
139290075Sobrien	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
139390075Sobrien		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
139490075Sobrien		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1395169689Skan		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
1396169689Skan		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
1397169689Skan		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
1398169689Skan		 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC;
139990075Sobrien
140090075Sobrien#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
140190075Sobrien	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
140290075Sobrien#endif
140390075Sobrien
140490075Sobrien#ifdef __ARMEB__
140590075Sobrien	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
140690075Sobrien#endif
1407132718Skan
140890075Sobrien	if (vector_page == ARM_VECTORS_HIGH)
140990075Sobrien		cpuctrl |= CPU_CONTROL_VECRELOC;
141090075Sobrien
141190075Sobrien	/* Clear out the cache */
141290075Sobrien	cpu_idcache_wbinv_all();
141390075Sobrien
141490075Sobrien	/* Set the control register */
141590075Sobrien	ctrl = cpuctrl;
141690075Sobrien	cpu_control(0xffffffff, cpuctrl);
141790075Sobrien}
141890075Sobrien#endif	/* CPU_FA526 || CPU_FA626TE */
141990075Sobrien
142090075Sobrien#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
142190075Sobrien  defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
142290075Sobrien  defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)
142390075Sobrienvoid
142490075Sobrienxscale_setup(void)
142590075Sobrien{
142690075Sobrien	uint32_t auxctl;
142790075Sobrien	int cpuctrl, cpuctrlmask;
142890075Sobrien
142990075Sobrien	/*
143090075Sobrien	 * The XScale Write Buffer is always enabled.  Our option
143190075Sobrien	 * is to enable/disable coalescing.  Note that bits 6:3
143290075Sobrien	 * must always be enabled.
143390075Sobrien	 */
143490075Sobrien
143590075Sobrien	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
143690075Sobrien		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
143790075Sobrien		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1438132718Skan		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
143990075Sobrien		 | CPU_CONTROL_BPRD_ENABLE;
144090075Sobrien	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
144190075Sobrien		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
144290075Sobrien		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
144390075Sobrien		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
144490075Sobrien		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
144590075Sobrien		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
144690075Sobrien		 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC | \
144790075Sobrien		 CPU_CONTROL_L2_ENABLE;
144890075Sobrien
144990075Sobrien#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
145090075Sobrien	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
145190075Sobrien#endif
145290075Sobrien
145396263Sobrien#ifdef __ARMEB__
145490075Sobrien	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
145596263Sobrien#endif
145696263Sobrien
1457132718Skan	if (vector_page == ARM_VECTORS_HIGH)
145896263Sobrien		cpuctrl |= CPU_CONTROL_VECRELOC;
145996263Sobrien#ifdef CPU_XSCALE_CORE3
146096263Sobrien	cpuctrl |= CPU_CONTROL_L2_ENABLE;
1461132718Skan#endif
146290075Sobrien
146390075Sobrien	/* Clear out the cache */
146496263Sobrien	cpu_idcache_wbinv_all();
146596263Sobrien
146696263Sobrien	/*
1467132718Skan	 * Set the control register.  Note that bits 6:3 must always
146890075Sobrien	 * be set to 1.
146990075Sobrien	 */
147096263Sobrien	ctrl = cpuctrl;
147196263Sobrien/*	cpu_control(cpuctrlmask, cpuctrl);*/
147296263Sobrien	cpu_control(0xffffffff, cpuctrl);
147390075Sobrien
147490075Sobrien	/* Make sure write coalescing is turned on */
147590075Sobrien	__asm __volatile("mrc p15, 0, %0, c1, c0, 1"
147690075Sobrien		: "=r" (auxctl));
147790075Sobrien#ifdef XSCALE_NO_COALESCE_WRITES
147890075Sobrien	auxctl |= XSCALE_AUXCTL_K;
147990075Sobrien#else
148090075Sobrien	auxctl &= ~XSCALE_AUXCTL_K;
148190075Sobrien#endif
148290075Sobrien#ifdef CPU_XSCALE_CORE3
148390075Sobrien	auxctl |= XSCALE_AUXCTL_LLR;
148490075Sobrien	auxctl |= XSCALE_AUXCTL_MD_MASK;
148590075Sobrien#endif
148690075Sobrien	__asm __volatile("mcr p15, 0, %0, c1, c0, 1"
148790075Sobrien		: : "r" (auxctl));
148890075Sobrien}
148990075Sobrien#endif	/* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425
149090075Sobrien	   CPU_XSCALE_80219 */
149190075Sobrien