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: stable/11/sys/arm/arm/cpufunc.c 317003 2017-04-16 06:51:06Z mmel $");
46129198Scognet
47129198Scognet#include <sys/param.h>
48129198Scognet#include <sys/systm.h>
49129198Scognet#include <sys/lock.h>
50129198Scognet#include <sys/mutex.h>
51132472Scognet#include <sys/bus.h>
52132472Scognet#include <machine/bus.h>
53129198Scognet#include <machine/cpu.h>
54129198Scognet#include <machine/disassem.h>
55129198Scognet
56129198Scognet#include <vm/vm.h>
57129198Scognet#include <vm/pmap.h>
58166655Scognet#include <vm/uma.h>
59129198Scognet
60129198Scognet#include <machine/cpufunc.h>
61129198Scognet
62295200Smmel#if defined(CPU_XSCALE_81342)
63164080Scognet#include <arm/xscale/i8134x/i81342reg.h>
64164080Scognet#endif
65164080Scognet
66129198Scognet#ifdef CPU_XSCALE_IXP425
67135646Scognet#include <arm/xscale/ixp425/ixp425reg.h>
68135646Scognet#include <arm/xscale/ixp425/ixp425var.h>
69129198Scognet#endif
70129198Scognet
71129198Scognet/* PRIMARY CACHE VARIABLES */
72129198Scognetint	arm_picache_size;
73129198Scognetint	arm_picache_line_size;
74129198Scognetint	arm_picache_ways;
75129198Scognet
76129198Scognetint	arm_pdcache_size;	/* and unified */
77129198Scognetint	arm_pdcache_line_size;
78129198Scognetint	arm_pdcache_ways;
79129198Scognet
80129198Scognetint	arm_pcache_type;
81129198Scognetint	arm_pcache_unified;
82129198Scognet
83129198Scognetint	arm_dcache_align;
84129198Scognetint	arm_dcache_align_mask;
85129198Scognet
86239268Sgonzou_int	arm_cache_level;
87239268Sgonzou_int	arm_cache_type[14];
88239268Sgonzou_int	arm_cache_loc;
89239268Sgonzo
90129198Scognet#ifdef CPU_ARM9
91129198Scognetstruct cpu_functions arm9_cpufuncs = {
92129198Scognet	/* CPU functions */
93129198Scognet
94129198Scognet	cpufunc_nullop,			/* cpwait		*/
95129198Scognet
96129198Scognet	/* MMU functions */
97129198Scognet
98129198Scognet	cpufunc_control,		/* control		*/
99129198Scognet	arm9_setttb,			/* Setttb		*/
100129198Scognet
101129198Scognet	/* TLB functions */
102129198Scognet
103129198Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
104129198Scognet	arm9_tlb_flushID_SE,		/* tlb_flushID_SE	*/
105129198Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
106129198Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
107129198Scognet
108129198Scognet	/* Cache operations */
109129198Scognet
110146605Scognet	arm9_icache_sync_range,		/* icache_sync_range	*/
111129198Scognet
112146605Scognet	arm9_dcache_wbinv_all,		/* dcache_wbinv_all	*/
113146605Scognet	arm9_dcache_wbinv_range,	/* dcache_wbinv_range	*/
114195798Sraj	arm9_dcache_inv_range,		/* dcache_inv_range	*/
115146605Scognet	arm9_dcache_wb_range,		/* dcache_wb_range	*/
116129198Scognet
117262420Sian	armv4_idcache_inv_all,		/* idcache_inv_all	*/
118146605Scognet	arm9_idcache_wbinv_all,		/* idcache_wbinv_all	*/
119146605Scognet	arm9_idcache_wbinv_range,	/* idcache_wbinv_range	*/
120171618Scognet	cpufunc_nullop,			/* l2cache_wbinv_all	*/
121171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
122171781Scognet	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
123171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
124265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
125129198Scognet
126129198Scognet	/* Other functions */
127129198Scognet
128129198Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
129129198Scognet
130129198Scognet	(void *)cpufunc_nullop,		/* sleep		*/
131129198Scognet
132129198Scognet	/* Soft functions */
133129198Scognet
134129198Scognet	arm9_context_switch,		/* context_switch	*/
135129198Scognet
136129198Scognet	arm9_setup			/* cpu setup		*/
137129198Scognet
138129198Scognet};
139129198Scognet#endif /* CPU_ARM9 */
140129198Scognet
141280809Sandrew#if defined(CPU_ARM9E)
142172738Simpstruct cpu_functions armv5_ec_cpufuncs = {
143172738Simp	/* CPU functions */
144172738Simp
145172738Simp	cpufunc_nullop,			/* cpwait		*/
146172738Simp
147172738Simp	/* MMU functions */
148172738Simp
149172738Simp	cpufunc_control,		/* control		*/
150172738Simp	armv5_ec_setttb,		/* Setttb		*/
151172738Simp
152172738Simp	/* TLB functions */
153172738Simp
154172738Simp	armv4_tlb_flushID,		/* tlb_flushID		*/
155295149Smmel	arm9_tlb_flushID_SE,		/* tlb_flushID_SE	*/
156172738Simp	armv4_tlb_flushD,		/* tlb_flushD		*/
157172738Simp	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
158172738Simp
159172738Simp	/* Cache operations */
160172738Simp
161172738Simp	armv5_ec_icache_sync_range,	/* icache_sync_range	*/
162172738Simp
163172738Simp	armv5_ec_dcache_wbinv_all,	/* dcache_wbinv_all	*/
164172738Simp	armv5_ec_dcache_wbinv_range,	/* dcache_wbinv_range	*/
165195798Sraj	armv5_ec_dcache_inv_range,	/* dcache_inv_range	*/
166172738Simp	armv5_ec_dcache_wb_range,	/* dcache_wb_range	*/
167172738Simp
168262420Sian	armv4_idcache_inv_all,		/* idcache_inv_all	*/
169172738Simp	armv5_ec_idcache_wbinv_all,	/* idcache_wbinv_all	*/
170172738Simp	armv5_ec_idcache_wbinv_range,	/* idcache_wbinv_range	*/
171172738Simp
172173442Scognet	cpufunc_nullop,                 /* l2cache_wbinv_all    */
173173442Scognet	(void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
174173442Scognet      	(void *)cpufunc_nullop,         /* l2cache_inv_range    */
175173442Scognet	(void *)cpufunc_nullop,         /* l2cache_wb_range     */
176265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
177236991Simp
178172738Simp	/* Other functions */
179172738Simp
180172738Simp	armv4_drain_writebuf,		/* drain_writebuf	*/
181172738Simp
182172738Simp	(void *)cpufunc_nullop,		/* sleep		*/
183172738Simp
184172738Simp	/* Soft functions */
185172738Simp
186295149Smmel	arm9_context_switch,		/* context_switch	*/
187172738Simp
188172738Simp	arm10_setup			/* cpu setup		*/
189172738Simp
190172738Simp};
191183835Sraj
192186933Srajstruct cpu_functions sheeva_cpufuncs = {
193183835Sraj	/* CPU functions */
194183835Sraj
195183835Sraj	cpufunc_nullop,			/* cpwait		*/
196183835Sraj
197183835Sraj	/* MMU functions */
198183835Sraj
199183835Sraj	cpufunc_control,		/* control		*/
200186933Sraj	sheeva_setttb,			/* Setttb		*/
201183835Sraj
202183835Sraj	/* TLB functions */
203183835Sraj
204183835Sraj	armv4_tlb_flushID,		/* tlb_flushID		*/
205295149Smmel	arm9_tlb_flushID_SE,		/* tlb_flushID_SE	*/
206183835Sraj	armv4_tlb_flushD,		/* tlb_flushD		*/
207183835Sraj	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
208183835Sraj
209183835Sraj	/* Cache operations */
210183835Sraj
211183835Sraj	armv5_ec_icache_sync_range,	/* icache_sync_range	*/
212183835Sraj
213183835Sraj	armv5_ec_dcache_wbinv_all,	/* dcache_wbinv_all	*/
214186933Sraj	sheeva_dcache_wbinv_range,	/* dcache_wbinv_range	*/
215186933Sraj	sheeva_dcache_inv_range,	/* dcache_inv_range	*/
216186933Sraj	sheeva_dcache_wb_range,		/* dcache_wb_range	*/
217183835Sraj
218262420Sian	armv4_idcache_inv_all,		/* idcache_inv_all	*/
219183835Sraj	armv5_ec_idcache_wbinv_all,	/* idcache_wbinv_all	*/
220186933Sraj	sheeva_idcache_wbinv_range,	/* idcache_wbinv_all	*/
221183835Sraj
222186933Sraj	sheeva_l2cache_wbinv_all,	/* l2cache_wbinv_all    */
223186933Sraj	sheeva_l2cache_wbinv_range,	/* l2cache_wbinv_range  */
224186933Sraj	sheeva_l2cache_inv_range,	/* l2cache_inv_range    */
225186933Sraj	sheeva_l2cache_wb_range,	/* l2cache_wb_range     */
226265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
227183835Sraj
228183835Sraj	/* Other functions */
229183835Sraj
230183835Sraj	armv4_drain_writebuf,		/* drain_writebuf	*/
231183835Sraj
232212825Smav	sheeva_cpu_sleep,		/* sleep		*/
233183835Sraj
234183835Sraj	/* Soft functions */
235183835Sraj
236295149Smmel	arm9_context_switch,		/* context_switch	*/
237183835Sraj
238183835Sraj	arm10_setup			/* cpu setup		*/
239183835Sraj};
240280809Sandrew#endif /* CPU_ARM9E */
241172738Simp
242239268Sgonzo#ifdef CPU_MV_PJ4B
243239268Sgonzostruct cpu_functions pj4bv7_cpufuncs = {
244239268Sgonzo
245239268Sgonzo	/* Cache operations */
246317002Smmel	.cf_l2cache_wbinv_all = (void *)cpufunc_nullop,
247317002Smmel	.cf_l2cache_wbinv_range = (void *)cpufunc_nullop,
248317002Smmel	.cf_l2cache_inv_range = (void *)cpufunc_nullop,
249317002Smmel	.cf_l2cache_wb_range = (void *)cpufunc_nullop,
250317002Smmel	.cf_l2cache_drain_writebuf = (void *)cpufunc_nullop,
251239268Sgonzo
252239268Sgonzo	/* Other functions */
253317002Smmel	.cf_sleep = (void *)cpufunc_nullop,
254239268Sgonzo
255239268Sgonzo	/* Soft functions */
256317002Smmel	.cf_setup = pj4bv7_setup
257239268Sgonzo};
258239268Sgonzo#endif /* CPU_MV_PJ4B */
259239268Sgonzo
260295200Smmel#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425)
261161592Scognet
262129198Scognetstruct cpu_functions xscale_cpufuncs = {
263129198Scognet	/* CPU functions */
264283366Sandrew
265129198Scognet	xscale_cpwait,			/* cpwait		*/
266129198Scognet
267129198Scognet	/* MMU functions */
268129198Scognet
269129198Scognet	xscale_control,			/* control		*/
270129198Scognet	xscale_setttb,			/* setttb		*/
271129198Scognet
272129198Scognet	/* TLB functions */
273129198Scognet
274129198Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
275129198Scognet	xscale_tlb_flushID_SE,		/* tlb_flushID_SE	*/
276129198Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
277129198Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
278129198Scognet
279129198Scognet	/* Cache operations */
280129198Scognet
281129198Scognet	xscale_cache_syncI_rng,		/* icache_sync_range	*/
282129198Scognet
283129198Scognet	xscale_cache_purgeD,		/* dcache_wbinv_all	*/
284129198Scognet	xscale_cache_purgeD_rng,	/* dcache_wbinv_range	*/
285129198Scognet	xscale_cache_flushD_rng,	/* dcache_inv_range	*/
286129198Scognet	xscale_cache_cleanD_rng,	/* dcache_wb_range	*/
287129198Scognet
288262420Sian	xscale_cache_flushID,		/* idcache_inv_all	*/
289129198Scognet	xscale_cache_purgeID,		/* idcache_wbinv_all	*/
290129198Scognet	xscale_cache_purgeID_rng,	/* idcache_wbinv_range	*/
291171618Scognet	cpufunc_nullop,			/* l2cache_wbinv_all 	*/
292171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
293171781Scognet	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
294171781Scognet	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
295265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
296129198Scognet
297129198Scognet	/* Other functions */
298129198Scognet
299129198Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
300129198Scognet
301129198Scognet	xscale_cpu_sleep,		/* sleep		*/
302129198Scognet
303129198Scognet	/* Soft functions */
304129198Scognet
305129198Scognet	xscale_context_switch,		/* context_switch	*/
306129198Scognet
307129198Scognet	xscale_setup			/* cpu setup		*/
308129198Scognet};
309129198Scognet#endif
310295200Smmel/* CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */
311129198Scognet
312164080Scognet#ifdef CPU_XSCALE_81342
313164080Scognetstruct cpu_functions xscalec3_cpufuncs = {
314164080Scognet	/* CPU functions */
315283366Sandrew
316164080Scognet	xscale_cpwait,			/* cpwait		*/
317164080Scognet
318164080Scognet	/* MMU functions */
319164080Scognet
320164080Scognet	xscale_control,			/* control		*/
321164080Scognet	xscalec3_setttb,		/* setttb		*/
322164080Scognet
323164080Scognet	/* TLB functions */
324164080Scognet
325164080Scognet	armv4_tlb_flushID,		/* tlb_flushID		*/
326164080Scognet	xscale_tlb_flushID_SE,		/* tlb_flushID_SE	*/
327164080Scognet	armv4_tlb_flushD,		/* tlb_flushD		*/
328164080Scognet	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
329164080Scognet
330164080Scognet	/* Cache operations */
331164080Scognet
332171618Scognet	xscalec3_cache_syncI_rng,	/* icache_sync_range	*/
333164080Scognet
334164080Scognet	xscalec3_cache_purgeD,		/* dcache_wbinv_all	*/
335164080Scognet	xscalec3_cache_purgeD_rng,	/* dcache_wbinv_range	*/
336164080Scognet	xscale_cache_flushD_rng,	/* dcache_inv_range	*/
337164080Scognet	xscalec3_cache_cleanD_rng,	/* dcache_wb_range	*/
338164080Scognet
339262420Sian	xscale_cache_flushID,		/* idcache_inv_all	*/
340171618Scognet	xscalec3_cache_purgeID,		/* idcache_wbinv_all	*/
341164080Scognet	xscalec3_cache_purgeID_rng,	/* idcache_wbinv_range	*/
342171618Scognet	xscalec3_l2cache_purge,		/* l2cache_wbinv_all	*/
343171618Scognet	xscalec3_l2cache_purge_rng,	/* l2cache_wbinv_range	*/
344171618Scognet	xscalec3_l2cache_flush_rng,	/* l2cache_inv_range	*/
345171618Scognet	xscalec3_l2cache_clean_rng,	/* l2cache_wb_range	*/
346265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
347164080Scognet
348164080Scognet	/* Other functions */
349164080Scognet
350164080Scognet	armv4_drain_writebuf,		/* drain_writebuf	*/
351164080Scognet
352164080Scognet	xscale_cpu_sleep,		/* sleep		*/
353164080Scognet
354164080Scognet	/* Soft functions */
355164080Scognet
356164080Scognet	xscalec3_context_switch,	/* context_switch	*/
357164080Scognet
358164080Scognet	xscale_setup			/* cpu setup		*/
359164080Scognet};
360164080Scognet#endif /* CPU_XSCALE_81342 */
361201468Srpaulo
362201468Srpaulo
363280842Sandrew#if defined(CPU_FA526)
364201468Srpaulostruct cpu_functions fa526_cpufuncs = {
365201468Srpaulo	/* CPU functions */
366201468Srpaulo
367207611Skevlo	cpufunc_nullop,			/* cpwait		*/
368201468Srpaulo
369201468Srpaulo	/* MMU functions */
370201468Srpaulo
371207611Skevlo	cpufunc_control,		/* control		*/
372207611Skevlo	fa526_setttb,			/* setttb		*/
373201468Srpaulo
374201468Srpaulo	/* TLB functions */
375201468Srpaulo
376207611Skevlo	armv4_tlb_flushID,		/* tlb_flushID		*/
377207611Skevlo	fa526_tlb_flushID_SE,		/* tlb_flushID_SE	*/
378207611Skevlo	armv4_tlb_flushD,		/* tlb_flushD		*/
379207611Skevlo	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
380201468Srpaulo
381201468Srpaulo	/* Cache operations */
382201468Srpaulo
383207611Skevlo	fa526_icache_sync_range,	/* icache_sync_range	*/
384201468Srpaulo
385207611Skevlo	fa526_dcache_wbinv_all,		/* dcache_wbinv_all	*/
386207611Skevlo	fa526_dcache_wbinv_range,	/* dcache_wbinv_range	*/
387207611Skevlo	fa526_dcache_inv_range,		/* dcache_inv_range	*/
388207611Skevlo	fa526_dcache_wb_range,		/* dcache_wb_range	*/
389201468Srpaulo
390262420Sian	armv4_idcache_inv_all,		/* idcache_inv_all	*/
391207611Skevlo	fa526_idcache_wbinv_all,	/* idcache_wbinv_all	*/
392207611Skevlo	fa526_idcache_wbinv_range,	/* idcache_wbinv_range	*/
393207611Skevlo	cpufunc_nullop,			/* l2cache_wbinv_all	*/
394207611Skevlo	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
395207611Skevlo	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
396207611Skevlo	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
397265870Sian	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
398201468Srpaulo
399201468Srpaulo	/* Other functions */
400201468Srpaulo
401207611Skevlo	armv4_drain_writebuf,		/* drain_writebuf	*/
402201468Srpaulo
403207611Skevlo	fa526_cpu_sleep,		/* sleep		*/
404201468Srpaulo
405201468Srpaulo	/* Soft functions */
406201468Srpaulo
407201468Srpaulo
408207611Skevlo	fa526_context_switch,		/* context_switch	*/
409201468Srpaulo
410207611Skevlo	fa526_setup			/* cpu setup 		*/
411236991Simp};
412280842Sandrew#endif	/* CPU_FA526 */
413201468Srpaulo
414244480Sgonzo#if defined(CPU_ARM1176)
415244480Sgonzostruct cpu_functions arm1176_cpufuncs = {
416283366Sandrew
417244480Sgonzo	/* Cache operations */
418317002Smmel	.cf_l2cache_wbinv_all = (void *)cpufunc_nullop,
419317002Smmel	.cf_l2cache_wbinv_range = (void *)cpufunc_nullop,
420317002Smmel	.cf_l2cache_inv_range = (void *)cpufunc_nullop,
421317002Smmel	.cf_l2cache_wb_range = (void *)cpufunc_nullop,
422317002Smmel	.cf_l2cache_drain_writebuf = (void *)cpufunc_nullop,
423283366Sandrew
424244480Sgonzo	/* Other functions */
425317002Smmel	.cf_sleep = arm11x6_sleep,
426283366Sandrew
427244480Sgonzo	/* Soft functions */
428317002Smmel	.cf_setup = arm11x6_setup
429244480Sgonzo};
430244480Sgonzo#endif /*CPU_ARM1176 */
431239701Sgonzo
432259640Sganbold#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
433239268Sgonzostruct cpu_functions cortexa_cpufuncs = {
434283366Sandrew
435239268Sgonzo	/* Cache operations */
436283366Sandrew
437283366Sandrew	/*
438243026Scognet	 * Note: For CPUs using the PL310 the L2 ops are filled in when the
439239268Sgonzo	 * L2 cache controller is actually enabled.
440239268Sgonzo	 */
441317002Smmel	.cf_l2cache_wbinv_all = cpufunc_nullop,
442317002Smmel	.cf_l2cache_wbinv_range = (void *)cpufunc_nullop,
443317002Smmel	.cf_l2cache_inv_range = (void *)cpufunc_nullop,
444317002Smmel	.cf_l2cache_wb_range = (void *)cpufunc_nullop,
445317002Smmel	.cf_l2cache_drain_writebuf = (void *)cpufunc_nullop,
446283366Sandrew
447239268Sgonzo	/* Other functions */
448317002Smmel	.cf_sleep = armv7_cpu_sleep,
449283366Sandrew
450239268Sgonzo	/* Soft functions */
451317002Smmel	.cf_setup = cortexa_setup
452239268Sgonzo};
453239268Sgonzo#endif /* CPU_CORTEXA */
454201468Srpaulo
455129198Scognet/*
456129198Scognet * Global constants also used by locore.s
457129198Scognet */
458129198Scognet
459129198Scognetstruct cpu_functions cpufuncs;
460129198Scognetu_int cputype;
461296313Sandrew#if __ARM_ARCH <= 5
462296313Sandrewu_int cpu_reset_needs_v4_MMU_disable;	/* flag used in locore-v4.s */
463296313Sandrew#endif
464129198Scognet
465262958Sian#if defined(CPU_ARM9) ||	\
466280824Sandrew  defined (CPU_ARM9E) ||	\
467295200Smmel  defined(CPU_ARM1176) ||	\
468207611Skevlo  defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) ||		\
469280842Sandrew  defined(CPU_FA526) || defined(CPU_MV_PJ4B) ||			\
470295200Smmel  defined(CPU_XSCALE_81342) || \
471259640Sganbold  defined(CPU_CORTEXA) || defined(CPU_KRAIT)
472161592Scognet
473278518Szbb/* Global cache line sizes, use 32 as default */
474278518Szbbint	arm_dcache_min_line_size = 32;
475278518Szbbint	arm_icache_min_line_size = 32;
476278518Szbbint	arm_idcache_min_line_size = 32;
477278518Szbb
478137498Strhodesstatic void get_cachetype_cp15(void);
479129198Scognet
480129198Scognet/* Additional cache information local to this file.  Log2 of some of the
481129198Scognet   above numbers.  */
482129198Scognetstatic int	arm_dcache_l2_nsets;
483129198Scognetstatic int	arm_dcache_l2_assoc;
484129198Scognetstatic int	arm_dcache_l2_linesize;
485129198Scognet
486129198Scognetstatic void
487314506Sianget_cachetype_cp15(void)
488129198Scognet{
489239268Sgonzo	u_int ctype, isize, dsize, cpuid;
490239268Sgonzo	u_int clevel, csize, i, sel;
491129198Scognet	u_int multiplier;
492239268Sgonzo	u_char type;
493129198Scognet
494129198Scognet	__asm __volatile("mrc p15, 0, %0, c0, c0, 1"
495129198Scognet		: "=r" (ctype));
496129198Scognet
497295096Smmel	cpuid = cpu_ident();
498129198Scognet	/*
499129198Scognet	 * ...and thus spake the ARM ARM:
500129198Scognet	 *
501129198Scognet	 * If an <opcode2> value corresponding to an unimplemented or
502129198Scognet	 * reserved ID register is encountered, the System Control
503129198Scognet	 * processor returns the value of the main ID register.
504129198Scognet	 */
505239268Sgonzo	if (ctype == cpuid)
506129198Scognet		goto out;
507129198Scognet
508239268Sgonzo	if (CPU_CT_FORMAT(ctype) == CPU_CT_ARMV7) {
509278518Szbb		/* Resolve minimal cache line sizes */
510278518Szbb		arm_dcache_min_line_size = 1 << (CPU_CT_DMINLINE(ctype) + 2);
511278518Szbb		arm_icache_min_line_size = 1 << (CPU_CT_IMINLINE(ctype) + 2);
512278518Szbb		arm_idcache_min_line_size =
513278518Szbb		    min(arm_icache_min_line_size, arm_dcache_min_line_size);
514278518Szbb
515239268Sgonzo		__asm __volatile("mrc p15, 1, %0, c0, c0, 1"
516239268Sgonzo		    : "=r" (clevel));
517239268Sgonzo		arm_cache_level = clevel;
518239268Sgonzo		arm_cache_loc = CPU_CLIDR_LOC(arm_cache_level);
519239268Sgonzo		i = 0;
520239268Sgonzo		while ((type = (clevel & 0x7)) && i < 7) {
521239268Sgonzo			if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
522239268Sgonzo			    type == CACHE_SEP_CACHE) {
523239268Sgonzo				sel = i << 1;
524239268Sgonzo				__asm __volatile("mcr p15, 2, %0, c0, c0, 0"
525239268Sgonzo				    : : "r" (sel));
526239268Sgonzo				__asm __volatile("mrc p15, 1, %0, c0, c0, 0"
527239268Sgonzo				    : "=r" (csize));
528239268Sgonzo				arm_cache_type[sel] = csize;
529283366Sandrew				arm_dcache_align = 1 <<
530239268Sgonzo				    (CPUV7_CT_xSIZE_LEN(csize) + 4);
531239268Sgonzo				arm_dcache_align_mask = arm_dcache_align - 1;
532239268Sgonzo			}
533239268Sgonzo			if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
534239268Sgonzo				sel = (i << 1) | 1;
535239268Sgonzo				__asm __volatile("mcr p15, 2, %0, c0, c0, 0"
536239268Sgonzo				    : : "r" (sel));
537239268Sgonzo				__asm __volatile("mrc p15, 1, %0, c0, c0, 0"
538239268Sgonzo				    : "=r" (csize));
539239268Sgonzo				arm_cache_type[sel] = csize;
540239268Sgonzo			}
541239268Sgonzo			i++;
542239268Sgonzo			clevel >>= 3;
543239268Sgonzo		}
544239268Sgonzo	} else {
545239268Sgonzo		if ((ctype & CPU_CT_S) == 0)
546239268Sgonzo			arm_pcache_unified = 1;
547129198Scognet
548239268Sgonzo		/*
549239268Sgonzo		 * If you want to know how this code works, go read the ARM ARM.
550239268Sgonzo		 */
551129198Scognet
552239268Sgonzo		arm_pcache_type = CPU_CT_CTYPE(ctype);
553129198Scognet
554239268Sgonzo		if (arm_pcache_unified == 0) {
555239268Sgonzo			isize = CPU_CT_ISIZE(ctype);
556239268Sgonzo			multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2;
557239268Sgonzo			arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3);
558239268Sgonzo			if (CPU_CT_xSIZE_ASSOC(isize) == 0) {
559239268Sgonzo				if (isize & CPU_CT_xSIZE_M)
560239268Sgonzo					arm_picache_line_size = 0; /* not present */
561239268Sgonzo				else
562239268Sgonzo					arm_picache_ways = 1;
563239268Sgonzo			} else {
564239268Sgonzo				arm_picache_ways = multiplier <<
565239268Sgonzo				    (CPU_CT_xSIZE_ASSOC(isize) - 1);
566239268Sgonzo			}
567239268Sgonzo			arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
568239268Sgonzo		}
569239268Sgonzo
570239268Sgonzo		dsize = CPU_CT_DSIZE(ctype);
571239268Sgonzo		multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
572239268Sgonzo		arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
573239268Sgonzo		if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
574239268Sgonzo			if (dsize & CPU_CT_xSIZE_M)
575239268Sgonzo				arm_pdcache_line_size = 0; /* not present */
576129198Scognet			else
577239268Sgonzo				arm_pdcache_ways = 1;
578129198Scognet		} else {
579239268Sgonzo			arm_pdcache_ways = multiplier <<
580239268Sgonzo			    (CPU_CT_xSIZE_ASSOC(dsize) - 1);
581129198Scognet		}
582239268Sgonzo		arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
583129198Scognet
584239268Sgonzo		arm_dcache_align = arm_pdcache_line_size;
585129198Scognet
586239268Sgonzo		arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2;
587239268Sgonzo		arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3;
588239268Sgonzo		arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) -
589239268Sgonzo		    CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize);
590129198Scognet
591239268Sgonzo	out:
592239268Sgonzo		arm_dcache_align_mask = arm_dcache_align - 1;
593239268Sgonzo	}
594129198Scognet}
595262958Sian#endif /* ARM9 || XSCALE */
596129198Scognet
597129198Scognet/*
598129198Scognet * Cannot panic here as we may not have a console yet ...
599129198Scognet */
600129198Scognet
601129198Scognetint
602314506Sianset_cpufuncs(void)
603129198Scognet{
604295096Smmel	cputype = cpu_ident();
605129198Scognet	cputype &= CPU_ID_CPU_MASK;
606129198Scognet
607129198Scognet#ifdef CPU_ARM9
608129198Scognet	if (((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD ||
609129198Scognet	     (cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_TI) &&
610129198Scognet	    (cputype & 0x0000f000) == 0x00009000) {
611129198Scognet		cpufuncs = arm9_cpufuncs;
612129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* V4 or higher */
613129198Scognet		get_cachetype_cp15();
614146605Scognet		arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize;
615146605Scognet		arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize +
616146605Scognet		    arm_dcache_l2_nsets)) - arm9_dcache_sets_inc;
617146605Scognet		arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc);
618146605Scognet		arm9_dcache_index_max = 0U - arm9_dcache_index_inc;
619137270Scognet		pmap_pte_init_generic();
620166655Scognet		goto out;
621129198Scognet	}
622129198Scognet#endif /* CPU_ARM9 */
623280809Sandrew#if defined(CPU_ARM9E)
624239268Sgonzo	if (cputype == CPU_ID_MV88FR131 || cputype == CPU_ID_MV88FR571_VD ||
625183835Sraj	    cputype == CPU_ID_MV88FR571_41) {
626239268Sgonzo		uint32_t sheeva_ctrl;
627183835Sraj
628239268Sgonzo		sheeva_ctrl = (MV_DC_STREAM_ENABLE | MV_BTB_DISABLE |
629239268Sgonzo		    MV_L2_ENABLE);
630239268Sgonzo		/*
631239268Sgonzo		 * Workaround for Marvell MV78100 CPU: Cache prefetch
632239268Sgonzo		 * mechanism may affect the cache coherency validity,
633239268Sgonzo		 * so it needs to be disabled.
634239268Sgonzo		 *
635239268Sgonzo		 * Refer to errata document MV-S501058-00C.pdf (p. 3.1
636239268Sgonzo		 * L2 Prefetching Mechanism) for details.
637239268Sgonzo		 */
638239268Sgonzo		if (cputype == CPU_ID_MV88FR571_VD ||
639239268Sgonzo		    cputype == CPU_ID_MV88FR571_41)
640239268Sgonzo			sheeva_ctrl |= MV_L2_PREFETCH_DISABLE;
641212825Smav
642239268Sgonzo		sheeva_control_ext(0xffffffff & ~MV_WA_ENABLE, sheeva_ctrl);
643183835Sraj
644239268Sgonzo		cpufuncs = sheeva_cpufuncs;
645172738Simp		get_cachetype_cp15();
646172738Simp		pmap_pte_init_generic();
647174058Scognet		goto out;
648280809Sandrew	} else if (cputype == CPU_ID_ARM926EJS) {
649239268Sgonzo		cpufuncs = armv5_ec_cpufuncs;
650239268Sgonzo		get_cachetype_cp15();
651239268Sgonzo		pmap_pte_init_generic();
652239268Sgonzo		goto out;
653172738Simp	}
654280809Sandrew#endif /* CPU_ARM9E */
655280824Sandrew#if defined(CPU_ARM1176)
656280824Sandrew	if (cputype == CPU_ID_ARM1176JZS) {
657280868Sandrew		cpufuncs = arm1176_cpufuncs;
658244480Sgonzo		get_cachetype_cp15();
659244480Sgonzo		goto out;
660244480Sgonzo	}
661280824Sandrew#endif /* CPU_ARM1176 */
662259640Sganbold#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
663301561Sandrew	switch(cputype & CPU_ID_SCHEME_MASK) {
664301561Sandrew	case CPU_ID_CORTEXA5:
665301561Sandrew	case CPU_ID_CORTEXA7:
666301561Sandrew	case CPU_ID_CORTEXA8:
667301561Sandrew	case CPU_ID_CORTEXA9:
668301561Sandrew	case CPU_ID_CORTEXA12:
669301561Sandrew	case CPU_ID_CORTEXA15:
670317002Smmel	case CPU_ID_CORTEXA53:
671317002Smmel	case CPU_ID_CORTEXA57:
672317002Smmel	case CPU_ID_CORTEXA72:
673301561Sandrew	case CPU_ID_KRAIT300:
674239268Sgonzo		cpufuncs = cortexa_cpufuncs;
675239268Sgonzo		get_cachetype_cp15();
676239268Sgonzo		goto out;
677301561Sandrew	default:
678301561Sandrew		break;
679239268Sgonzo	}
680239268Sgonzo#endif /* CPU_CORTEXA */
681283366Sandrew
682239268Sgonzo#if defined(CPU_MV_PJ4B)
683257281Szbb	if (cputype == CPU_ID_MV88SV581X_V7 ||
684240486Sgber	    cputype == CPU_ID_MV88SV584X_V7 ||
685239268Sgonzo	    cputype == CPU_ID_ARM_88SV581X_V7) {
686257281Szbb		cpufuncs = pj4bv7_cpufuncs;
687239268Sgonzo		get_cachetype_cp15();
688239268Sgonzo		goto out;
689239268Sgonzo	}
690239268Sgonzo#endif /* CPU_MV_PJ4B */
691129198Scognet
692280842Sandrew#if defined(CPU_FA526)
693207611Skevlo	if (cputype == CPU_ID_FA526 || cputype == CPU_ID_FA626TE) {
694201468Srpaulo		cpufuncs = fa526_cpufuncs;
695201468Srpaulo		cpu_reset_needs_v4_MMU_disable = 1;	/* SA needs it	*/
696201468Srpaulo		get_cachetype_cp15();
697201468Srpaulo		pmap_pte_init_generic();
698201468Srpaulo
699201468Srpaulo		goto out;
700201468Srpaulo	}
701280842Sandrew#endif	/* CPU_FA526 */
702262958Sian
703164080Scognet#if defined(CPU_XSCALE_81342)
704164080Scognet	if (cputype == CPU_ID_81342) {
705164080Scognet		cpufuncs = xscalec3_cpufuncs;
706164080Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
707164080Scognet		get_cachetype_cp15();
708164080Scognet		pmap_pte_init_xscale();
709166655Scognet		goto out;
710164080Scognet	}
711164080Scognet#endif /* CPU_XSCALE_81342 */
712129198Scognet#ifdef CPU_XSCALE_PXA2X0
713129198Scognet	/* ignore core revision to test PXA2xx CPUs */
714129198Scognet	if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA250 ||
715191817Sstas	    (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X ||
716129198Scognet	    (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA210) {
717129198Scognet
718129198Scognet		cpufuncs = xscale_cpufuncs;
719129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
720129198Scognet		get_cachetype_cp15();
721129198Scognet		pmap_pte_init_xscale();
722129198Scognet
723166655Scognet		goto out;
724129198Scognet	}
725129198Scognet#endif /* CPU_XSCALE_PXA2X0 */
726129198Scognet#ifdef CPU_XSCALE_IXP425
727129198Scognet	if (cputype == CPU_ID_IXP425_533 || cputype == CPU_ID_IXP425_400 ||
728186352Ssam            cputype == CPU_ID_IXP425_266 || cputype == CPU_ID_IXP435) {
729129198Scognet
730129198Scognet		cpufuncs = xscale_cpufuncs;
731129198Scognet		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
732129198Scognet		get_cachetype_cp15();
733129198Scognet		pmap_pte_init_xscale();
734129198Scognet
735166655Scognet		goto out;
736129198Scognet	}
737129198Scognet#endif /* CPU_XSCALE_IXP425 */
738129198Scognet	/*
739129198Scognet	 * Bzzzz. And the answer was ...
740129198Scognet	 */
741129198Scognet	panic("No support for this CPU type (%08x) in kernel", cputype);
742129198Scognet	return(ARCHITECTURE_NOT_PRESENT);
743166655Scognetout:
744166655Scognet	uma_set_align(arm_dcache_align_mask);
745166655Scognet	return (0);
746129198Scognet}
747129198Scognet
748129198Scognet/*
749129198Scognet * CPU Setup code
750129198Scognet */
751129198Scognet
752129198Scognet#ifdef CPU_ARM9
753129198Scognetvoid
754280823Sandrewarm9_setup(void)
755129198Scognet{
756129198Scognet	int cpuctrl, cpuctrlmask;
757129198Scognet
758129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
759129198Scognet	    | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
760129198Scognet	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
761157618Scognet	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE |
762157618Scognet	    CPU_CONTROL_ROUNDROBIN;
763129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
764129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
765129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
766129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
767129198Scognet		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
768146605Scognet		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_VECRELOC
769146605Scognet		 | CPU_CONTROL_ROUNDROBIN;
770129198Scognet
771129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
772129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
773129198Scognet#endif
774129198Scognet
775129198Scognet#ifdef __ARMEB__
776129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
777129198Scognet#endif
778142050Scognet	if (vector_page == ARM_VECTORS_HIGH)
779142050Scognet		cpuctrl |= CPU_CONTROL_VECRELOC;
780129198Scognet
781129198Scognet	/* Clear out the cache */
782129198Scognet	cpu_idcache_wbinv_all();
783129198Scognet
784300533Sian	/* Set the control register (SCTLR)   */
785146605Scognet	cpu_control(cpuctrlmask, cpuctrl);
786129198Scognet
787129198Scognet}
788129198Scognet#endif	/* CPU_ARM9 */
789129198Scognet
790280809Sandrew#if defined(CPU_ARM9E)
791129198Scognetvoid
792280823Sandrewarm10_setup(void)
793129198Scognet{
794129198Scognet	int cpuctrl, cpuctrlmask;
795129198Scognet
796129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
797236991Simp	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
798129198Scognet	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE;
799129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
800129198Scognet	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
801129198Scognet	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
802129198Scognet	    | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
803129198Scognet	    | CPU_CONTROL_BPRD_ENABLE
804129198Scognet	    | CPU_CONTROL_ROUNDROBIN | CPU_CONTROL_CPCLK;
805129198Scognet
806129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
807129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
808129198Scognet#endif
809129198Scognet
810129198Scognet#ifdef __ARMEB__
811129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
812129198Scognet#endif
813129198Scognet
814129198Scognet	/* Clear out the cache */
815129198Scognet	cpu_idcache_wbinv_all();
816129198Scognet
817129198Scognet	/* Now really make sure they are clean.  */
818172738Simp	__asm __volatile ("mcr\tp15, 0, r0, c7, c7, 0" : : );
819129198Scognet
820174058Scognet	if (vector_page == ARM_VECTORS_HIGH)
821174058Scognet		cpuctrl |= CPU_CONTROL_VECRELOC;
822174058Scognet
823129198Scognet	/* Set the control register */
824129198Scognet	cpu_control(0xffffffff, cpuctrl);
825129198Scognet
826129198Scognet	/* And again. */
827129198Scognet	cpu_idcache_wbinv_all();
828129198Scognet}
829172738Simp#endif	/* CPU_ARM9E || CPU_ARM10 */
830129198Scognet
831280824Sandrew#if defined(CPU_ARM1176) \
832266083Smarkm || defined(CPU_MV_PJ4B) \
833266083Smarkm || defined(CPU_CORTEXA) || defined(CPU_KRAIT)
834266083Smarkmstatic __inline void
835266083Smarkmcpu_scc_setup_ccnt(void)
836266083Smarkm{
837266083Smarkm/* This is how you give userland access to the CCNT and PMCn
838266083Smarkm * registers.
839266083Smarkm * BEWARE! This gives write access also, which may not be what
840266083Smarkm * you want!
841266083Smarkm */
842266083Smarkm#ifdef _PMC_USER_READ_WRITE_
843266083Smarkm	/* Set PMUSERENR[0] to allow userland access */
844283365Sandrew	cp15_pmuserenr_set(1);
845266083Smarkm#endif
846280824Sandrew#if defined(CPU_ARM1176)
847267597Stuexen	/* Set PMCR[2,0] to enable counters and reset CCNT */
848283365Sandrew	cp15_pmcr_set(5);
849267597Stuexen#else
850267597Stuexen	/* Set up the PMCCNTR register as a cyclecounter:
851266083Smarkm	 * Set PMINTENCLR to 0xFFFFFFFF to block interrupts
852266083Smarkm	 * Set PMCR[2,0] to enable counters and reset CCNT
853266083Smarkm	 * Set PMCNTENSET to 0x80000000 to enable CCNT */
854283365Sandrew	cp15_pminten_clr(0xFFFFFFFF);
855283365Sandrew	cp15_pmcr_set(5);
856283365Sandrew	cp15_pmcnten_set(0x80000000);
857267597Stuexen#endif
858266083Smarkm}
859266083Smarkm#endif
860266083Smarkm
861280824Sandrew#if defined(CPU_ARM1176)
862172738Simpvoid
863280823Sandrewarm11x6_setup(void)
864172738Simp{
865244480Sgonzo	uint32_t auxctrl, auxctrl_wax;
866244480Sgonzo	uint32_t tmp, tmp2;
867244480Sgonzo	uint32_t cpuid;
868172738Simp
869295096Smmel	cpuid = cpu_ident();
870244480Sgonzo
871244480Sgonzo	auxctrl = 0;
872244480Sgonzo	auxctrl_wax = ~0;
873244480Sgonzo
874244480Sgonzo	/*
875244480Sgonzo	 * Enable an errata workaround
876244480Sgonzo	 */
877244480Sgonzo	if ((cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM1176JZS) { /* ARM1176JZSr0 */
878244480Sgonzo		auxctrl = ARM1176_AUXCTL_PHD;
879244480Sgonzo		auxctrl_wax = ~ARM1176_AUXCTL_PHD;
880244480Sgonzo	}
881244480Sgonzo
882283365Sandrew	tmp = cp15_actlr_get();
883283365Sandrew	tmp2 = tmp;
884283365Sandrew	tmp &= auxctrl_wax;
885283365Sandrew	tmp |= auxctrl;
886283365Sandrew	if (tmp != tmp2)
887283365Sandrew		cp15_actlr_set(tmp);
888244480Sgonzo
889266083Smarkm	cpu_scc_setup_ccnt();
890172738Simp}
891280824Sandrew#endif  /* CPU_ARM1176 */
892172738Simp
893239268Sgonzo#ifdef CPU_MV_PJ4B
894239268Sgonzovoid
895280823Sandrewpj4bv7_setup(void)
896239268Sgonzo{
897239268Sgonzo
898239268Sgonzo	pj4b_config();
899266083Smarkm	cpu_scc_setup_ccnt();
900239268Sgonzo}
901239268Sgonzo#endif /* CPU_MV_PJ4B */
902239268Sgonzo
903259640Sganbold#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
904239268Sgonzo
905239268Sgonzovoid
906280823Sandrewcortexa_setup(void)
907239268Sgonzo{
908283366Sandrew
909266083Smarkm	cpu_scc_setup_ccnt();
910239268Sgonzo}
911239268Sgonzo#endif  /* CPU_CORTEXA */
912239268Sgonzo
913280842Sandrew#if defined(CPU_FA526)
914201468Srpaulovoid
915280823Sandrewfa526_setup(void)
916201468Srpaulo{
917201468Srpaulo	int cpuctrl, cpuctrlmask;
918201468Srpaulo
919201468Srpaulo	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
920201468Srpaulo		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
921201468Srpaulo		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
922204122Skevlo		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
923204122Skevlo		| CPU_CONTROL_BPRD_ENABLE;
924201468Srpaulo	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
925201468Srpaulo		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
926201468Srpaulo		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
927201468Srpaulo		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
928201468Srpaulo		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
929201468Srpaulo		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
930201468Srpaulo		 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC;
931201468Srpaulo
932201468Srpaulo#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
933201468Srpaulo	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
934201468Srpaulo#endif
935201468Srpaulo
936201468Srpaulo#ifdef __ARMEB__
937201468Srpaulo	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
938201468Srpaulo#endif
939201468Srpaulo
940201468Srpaulo	if (vector_page == ARM_VECTORS_HIGH)
941201468Srpaulo		cpuctrl |= CPU_CONTROL_VECRELOC;
942201468Srpaulo
943201468Srpaulo	/* Clear out the cache */
944201468Srpaulo	cpu_idcache_wbinv_all();
945201468Srpaulo
946201468Srpaulo	/* Set the control register */
947201468Srpaulo	cpu_control(0xffffffff, cpuctrl);
948201468Srpaulo}
949280842Sandrew#endif	/* CPU_FA526 */
950201468Srpaulo
951295200Smmel#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
952295200Smmel  defined(CPU_XSCALE_81342)
953129198Scognetvoid
954280823Sandrewxscale_setup(void)
955129198Scognet{
956129198Scognet	uint32_t auxctl;
957129198Scognet	int cpuctrl, cpuctrlmask;
958129198Scognet
959129198Scognet	/*
960129198Scognet	 * The XScale Write Buffer is always enabled.  Our option
961129198Scognet	 * is to enable/disable coalescing.  Note that bits 6:3
962129198Scognet	 * must always be enabled.
963129198Scognet	 */
964129198Scognet
965129198Scognet	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
966129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
967129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
968129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
969129198Scognet		 | CPU_CONTROL_BPRD_ENABLE;
970129198Scognet	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
971129198Scognet		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
972129198Scognet		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
973129198Scognet		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
974129198Scognet		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
975129198Scognet		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
976171618Scognet		 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC | \
977171618Scognet		 CPU_CONTROL_L2_ENABLE;
978129198Scognet
979129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
980129198Scognet	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
981129198Scognet#endif
982129198Scognet
983129198Scognet#ifdef __ARMEB__
984129198Scognet	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
985129198Scognet#endif
986129198Scognet
987129198Scognet	if (vector_page == ARM_VECTORS_HIGH)
988129198Scognet		cpuctrl |= CPU_CONTROL_VECRELOC;
989171618Scognet#ifdef CPU_XSCALE_CORE3
990171618Scognet	cpuctrl |= CPU_CONTROL_L2_ENABLE;
991171618Scognet#endif
992129198Scognet
993129198Scognet	/* Clear out the cache */
994129198Scognet	cpu_idcache_wbinv_all();
995129198Scognet
996129198Scognet	/*
997129198Scognet	 * Set the control register.  Note that bits 6:3 must always
998129198Scognet	 * be set to 1.
999129198Scognet	 */
1000129198Scognet/*	cpu_control(cpuctrlmask, cpuctrl);*/
1001129198Scognet	cpu_control(0xffffffff, cpuctrl);
1002129198Scognet
1003129198Scognet	/* Make sure write coalescing is turned on */
1004129198Scognet	__asm __volatile("mrc p15, 0, %0, c1, c0, 1"
1005129198Scognet		: "=r" (auxctl));
1006129198Scognet#ifdef XSCALE_NO_COALESCE_WRITES
1007129198Scognet	auxctl |= XSCALE_AUXCTL_K;
1008129198Scognet#else
1009129198Scognet	auxctl &= ~XSCALE_AUXCTL_K;
1010129198Scognet#endif
1011171618Scognet#ifdef CPU_XSCALE_CORE3
1012171618Scognet	auxctl |= XSCALE_AUXCTL_LLR;
1013171618Scognet	auxctl |= XSCALE_AUXCTL_MD_MASK;
1014171618Scognet#endif
1015129198Scognet	__asm __volatile("mcr p15, 0, %0, c1, c0, 1"
1016129198Scognet		: : "r" (auxctl));
1017129198Scognet}
1018295200Smmel#endif	/* CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */
1019