1/*	$NetBSD: cpufunc.c,v 1.65 2003/11/05 12:53:15 scw Exp $	*/
2
3/*-
4 * arm9 support code Copyright (C) 2001 ARM Ltd
5 * Copyright (c) 1997 Mark Brinicombe.
6 * Copyright (c) 1997 Causality Limited
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *	This product includes software developed by Causality Limited.
20 * 4. The name of Causality Limited may not be used to endorse or promote
21 *    products derived from this software without specific prior written
22 *    permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
25 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
28 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * RiscBSD kernel project
37 *
38 * cpufuncs.c
39 *
40 * C functions for supporting CPU / MMU / TLB specific operations.
41 *
42 * Created      : 30/01/97
43 */
44#include <sys/cdefs.h>
45__FBSDID("$FreeBSD: stable/11/sys/arm/arm/cpufunc.c 317003 2017-04-16 06:51:06Z mmel $");
46
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/lock.h>
50#include <sys/mutex.h>
51#include <sys/bus.h>
52#include <machine/bus.h>
53#include <machine/cpu.h>
54#include <machine/disassem.h>
55
56#include <vm/vm.h>
57#include <vm/pmap.h>
58#include <vm/uma.h>
59
60#include <machine/cpufunc.h>
61
62#if defined(CPU_XSCALE_81342)
63#include <arm/xscale/i8134x/i81342reg.h>
64#endif
65
66#ifdef CPU_XSCALE_IXP425
67#include <arm/xscale/ixp425/ixp425reg.h>
68#include <arm/xscale/ixp425/ixp425var.h>
69#endif
70
71/* PRIMARY CACHE VARIABLES */
72int	arm_picache_size;
73int	arm_picache_line_size;
74int	arm_picache_ways;
75
76int	arm_pdcache_size;	/* and unified */
77int	arm_pdcache_line_size;
78int	arm_pdcache_ways;
79
80int	arm_pcache_type;
81int	arm_pcache_unified;
82
83int	arm_dcache_align;
84int	arm_dcache_align_mask;
85
86u_int	arm_cache_level;
87u_int	arm_cache_type[14];
88u_int	arm_cache_loc;
89
90#ifdef CPU_ARM9
91struct cpu_functions arm9_cpufuncs = {
92	/* CPU functions */
93
94	cpufunc_nullop,			/* cpwait		*/
95
96	/* MMU functions */
97
98	cpufunc_control,		/* control		*/
99	arm9_setttb,			/* Setttb		*/
100
101	/* TLB functions */
102
103	armv4_tlb_flushID,		/* tlb_flushID		*/
104	arm9_tlb_flushID_SE,		/* tlb_flushID_SE	*/
105	armv4_tlb_flushD,		/* tlb_flushD		*/
106	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
107
108	/* Cache operations */
109
110	arm9_icache_sync_range,		/* icache_sync_range	*/
111
112	arm9_dcache_wbinv_all,		/* dcache_wbinv_all	*/
113	arm9_dcache_wbinv_range,	/* dcache_wbinv_range	*/
114	arm9_dcache_inv_range,		/* dcache_inv_range	*/
115	arm9_dcache_wb_range,		/* dcache_wb_range	*/
116
117	armv4_idcache_inv_all,		/* idcache_inv_all	*/
118	arm9_idcache_wbinv_all,		/* idcache_wbinv_all	*/
119	arm9_idcache_wbinv_range,	/* idcache_wbinv_range	*/
120	cpufunc_nullop,			/* l2cache_wbinv_all	*/
121	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
122	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
123	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
124	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
125
126	/* Other functions */
127
128	armv4_drain_writebuf,		/* drain_writebuf	*/
129
130	(void *)cpufunc_nullop,		/* sleep		*/
131
132	/* Soft functions */
133
134	arm9_context_switch,		/* context_switch	*/
135
136	arm9_setup			/* cpu setup		*/
137
138};
139#endif /* CPU_ARM9 */
140
141#if defined(CPU_ARM9E)
142struct cpu_functions armv5_ec_cpufuncs = {
143	/* CPU functions */
144
145	cpufunc_nullop,			/* cpwait		*/
146
147	/* MMU functions */
148
149	cpufunc_control,		/* control		*/
150	armv5_ec_setttb,		/* Setttb		*/
151
152	/* TLB functions */
153
154	armv4_tlb_flushID,		/* tlb_flushID		*/
155	arm9_tlb_flushID_SE,		/* tlb_flushID_SE	*/
156	armv4_tlb_flushD,		/* tlb_flushD		*/
157	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
158
159	/* Cache operations */
160
161	armv5_ec_icache_sync_range,	/* icache_sync_range	*/
162
163	armv5_ec_dcache_wbinv_all,	/* dcache_wbinv_all	*/
164	armv5_ec_dcache_wbinv_range,	/* dcache_wbinv_range	*/
165	armv5_ec_dcache_inv_range,	/* dcache_inv_range	*/
166	armv5_ec_dcache_wb_range,	/* dcache_wb_range	*/
167
168	armv4_idcache_inv_all,		/* idcache_inv_all	*/
169	armv5_ec_idcache_wbinv_all,	/* idcache_wbinv_all	*/
170	armv5_ec_idcache_wbinv_range,	/* idcache_wbinv_range	*/
171
172	cpufunc_nullop,                 /* l2cache_wbinv_all    */
173	(void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
174      	(void *)cpufunc_nullop,         /* l2cache_inv_range    */
175	(void *)cpufunc_nullop,         /* l2cache_wb_range     */
176	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
177
178	/* Other functions */
179
180	armv4_drain_writebuf,		/* drain_writebuf	*/
181
182	(void *)cpufunc_nullop,		/* sleep		*/
183
184	/* Soft functions */
185
186	arm9_context_switch,		/* context_switch	*/
187
188	arm10_setup			/* cpu setup		*/
189
190};
191
192struct cpu_functions sheeva_cpufuncs = {
193	/* CPU functions */
194
195	cpufunc_nullop,			/* cpwait		*/
196
197	/* MMU functions */
198
199	cpufunc_control,		/* control		*/
200	sheeva_setttb,			/* Setttb		*/
201
202	/* TLB functions */
203
204	armv4_tlb_flushID,		/* tlb_flushID		*/
205	arm9_tlb_flushID_SE,		/* tlb_flushID_SE	*/
206	armv4_tlb_flushD,		/* tlb_flushD		*/
207	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
208
209	/* Cache operations */
210
211	armv5_ec_icache_sync_range,	/* icache_sync_range	*/
212
213	armv5_ec_dcache_wbinv_all,	/* dcache_wbinv_all	*/
214	sheeva_dcache_wbinv_range,	/* dcache_wbinv_range	*/
215	sheeva_dcache_inv_range,	/* dcache_inv_range	*/
216	sheeva_dcache_wb_range,		/* dcache_wb_range	*/
217
218	armv4_idcache_inv_all,		/* idcache_inv_all	*/
219	armv5_ec_idcache_wbinv_all,	/* idcache_wbinv_all	*/
220	sheeva_idcache_wbinv_range,	/* idcache_wbinv_all	*/
221
222	sheeva_l2cache_wbinv_all,	/* l2cache_wbinv_all    */
223	sheeva_l2cache_wbinv_range,	/* l2cache_wbinv_range  */
224	sheeva_l2cache_inv_range,	/* l2cache_inv_range    */
225	sheeva_l2cache_wb_range,	/* l2cache_wb_range     */
226	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
227
228	/* Other functions */
229
230	armv4_drain_writebuf,		/* drain_writebuf	*/
231
232	sheeva_cpu_sleep,		/* sleep		*/
233
234	/* Soft functions */
235
236	arm9_context_switch,		/* context_switch	*/
237
238	arm10_setup			/* cpu setup		*/
239};
240#endif /* CPU_ARM9E */
241
242#ifdef CPU_MV_PJ4B
243struct cpu_functions pj4bv7_cpufuncs = {
244
245	/* Cache operations */
246	.cf_l2cache_wbinv_all = (void *)cpufunc_nullop,
247	.cf_l2cache_wbinv_range = (void *)cpufunc_nullop,
248	.cf_l2cache_inv_range = (void *)cpufunc_nullop,
249	.cf_l2cache_wb_range = (void *)cpufunc_nullop,
250	.cf_l2cache_drain_writebuf = (void *)cpufunc_nullop,
251
252	/* Other functions */
253	.cf_sleep = (void *)cpufunc_nullop,
254
255	/* Soft functions */
256	.cf_setup = pj4bv7_setup
257};
258#endif /* CPU_MV_PJ4B */
259
260#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425)
261
262struct cpu_functions xscale_cpufuncs = {
263	/* CPU functions */
264
265	xscale_cpwait,			/* cpwait		*/
266
267	/* MMU functions */
268
269	xscale_control,			/* control		*/
270	xscale_setttb,			/* setttb		*/
271
272	/* TLB functions */
273
274	armv4_tlb_flushID,		/* tlb_flushID		*/
275	xscale_tlb_flushID_SE,		/* tlb_flushID_SE	*/
276	armv4_tlb_flushD,		/* tlb_flushD		*/
277	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
278
279	/* Cache operations */
280
281	xscale_cache_syncI_rng,		/* icache_sync_range	*/
282
283	xscale_cache_purgeD,		/* dcache_wbinv_all	*/
284	xscale_cache_purgeD_rng,	/* dcache_wbinv_range	*/
285	xscale_cache_flushD_rng,	/* dcache_inv_range	*/
286	xscale_cache_cleanD_rng,	/* dcache_wb_range	*/
287
288	xscale_cache_flushID,		/* idcache_inv_all	*/
289	xscale_cache_purgeID,		/* idcache_wbinv_all	*/
290	xscale_cache_purgeID_rng,	/* idcache_wbinv_range	*/
291	cpufunc_nullop,			/* l2cache_wbinv_all 	*/
292	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
293	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
294	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
295	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
296
297	/* Other functions */
298
299	armv4_drain_writebuf,		/* drain_writebuf	*/
300
301	xscale_cpu_sleep,		/* sleep		*/
302
303	/* Soft functions */
304
305	xscale_context_switch,		/* context_switch	*/
306
307	xscale_setup			/* cpu setup		*/
308};
309#endif
310/* CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */
311
312#ifdef CPU_XSCALE_81342
313struct cpu_functions xscalec3_cpufuncs = {
314	/* CPU functions */
315
316	xscale_cpwait,			/* cpwait		*/
317
318	/* MMU functions */
319
320	xscale_control,			/* control		*/
321	xscalec3_setttb,		/* setttb		*/
322
323	/* TLB functions */
324
325	armv4_tlb_flushID,		/* tlb_flushID		*/
326	xscale_tlb_flushID_SE,		/* tlb_flushID_SE	*/
327	armv4_tlb_flushD,		/* tlb_flushD		*/
328	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
329
330	/* Cache operations */
331
332	xscalec3_cache_syncI_rng,	/* icache_sync_range	*/
333
334	xscalec3_cache_purgeD,		/* dcache_wbinv_all	*/
335	xscalec3_cache_purgeD_rng,	/* dcache_wbinv_range	*/
336	xscale_cache_flushD_rng,	/* dcache_inv_range	*/
337	xscalec3_cache_cleanD_rng,	/* dcache_wb_range	*/
338
339	xscale_cache_flushID,		/* idcache_inv_all	*/
340	xscalec3_cache_purgeID,		/* idcache_wbinv_all	*/
341	xscalec3_cache_purgeID_rng,	/* idcache_wbinv_range	*/
342	xscalec3_l2cache_purge,		/* l2cache_wbinv_all	*/
343	xscalec3_l2cache_purge_rng,	/* l2cache_wbinv_range	*/
344	xscalec3_l2cache_flush_rng,	/* l2cache_inv_range	*/
345	xscalec3_l2cache_clean_rng,	/* l2cache_wb_range	*/
346	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
347
348	/* Other functions */
349
350	armv4_drain_writebuf,		/* drain_writebuf	*/
351
352	xscale_cpu_sleep,		/* sleep		*/
353
354	/* Soft functions */
355
356	xscalec3_context_switch,	/* context_switch	*/
357
358	xscale_setup			/* cpu setup		*/
359};
360#endif /* CPU_XSCALE_81342 */
361
362
363#if defined(CPU_FA526)
364struct cpu_functions fa526_cpufuncs = {
365	/* CPU functions */
366
367	cpufunc_nullop,			/* cpwait		*/
368
369	/* MMU functions */
370
371	cpufunc_control,		/* control		*/
372	fa526_setttb,			/* setttb		*/
373
374	/* TLB functions */
375
376	armv4_tlb_flushID,		/* tlb_flushID		*/
377	fa526_tlb_flushID_SE,		/* tlb_flushID_SE	*/
378	armv4_tlb_flushD,		/* tlb_flushD		*/
379	armv4_tlb_flushD_SE,		/* tlb_flushD_SE	*/
380
381	/* Cache operations */
382
383	fa526_icache_sync_range,	/* icache_sync_range	*/
384
385	fa526_dcache_wbinv_all,		/* dcache_wbinv_all	*/
386	fa526_dcache_wbinv_range,	/* dcache_wbinv_range	*/
387	fa526_dcache_inv_range,		/* dcache_inv_range	*/
388	fa526_dcache_wb_range,		/* dcache_wb_range	*/
389
390	armv4_idcache_inv_all,		/* idcache_inv_all	*/
391	fa526_idcache_wbinv_all,	/* idcache_wbinv_all	*/
392	fa526_idcache_wbinv_range,	/* idcache_wbinv_range	*/
393	cpufunc_nullop,			/* l2cache_wbinv_all	*/
394	(void *)cpufunc_nullop,		/* l2cache_wbinv_range	*/
395	(void *)cpufunc_nullop,		/* l2cache_inv_range	*/
396	(void *)cpufunc_nullop,		/* l2cache_wb_range	*/
397	(void *)cpufunc_nullop,         /* l2cache_drain_writebuf */
398
399	/* Other functions */
400
401	armv4_drain_writebuf,		/* drain_writebuf	*/
402
403	fa526_cpu_sleep,		/* sleep		*/
404
405	/* Soft functions */
406
407
408	fa526_context_switch,		/* context_switch	*/
409
410	fa526_setup			/* cpu setup 		*/
411};
412#endif	/* CPU_FA526 */
413
414#if defined(CPU_ARM1176)
415struct cpu_functions arm1176_cpufuncs = {
416
417	/* Cache operations */
418	.cf_l2cache_wbinv_all = (void *)cpufunc_nullop,
419	.cf_l2cache_wbinv_range = (void *)cpufunc_nullop,
420	.cf_l2cache_inv_range = (void *)cpufunc_nullop,
421	.cf_l2cache_wb_range = (void *)cpufunc_nullop,
422	.cf_l2cache_drain_writebuf = (void *)cpufunc_nullop,
423
424	/* Other functions */
425	.cf_sleep = arm11x6_sleep,
426
427	/* Soft functions */
428	.cf_setup = arm11x6_setup
429};
430#endif /*CPU_ARM1176 */
431
432#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
433struct cpu_functions cortexa_cpufuncs = {
434
435	/* Cache operations */
436
437	/*
438	 * Note: For CPUs using the PL310 the L2 ops are filled in when the
439	 * L2 cache controller is actually enabled.
440	 */
441	.cf_l2cache_wbinv_all = cpufunc_nullop,
442	.cf_l2cache_wbinv_range = (void *)cpufunc_nullop,
443	.cf_l2cache_inv_range = (void *)cpufunc_nullop,
444	.cf_l2cache_wb_range = (void *)cpufunc_nullop,
445	.cf_l2cache_drain_writebuf = (void *)cpufunc_nullop,
446
447	/* Other functions */
448	.cf_sleep = armv7_cpu_sleep,
449
450	/* Soft functions */
451	.cf_setup = cortexa_setup
452};
453#endif /* CPU_CORTEXA */
454
455/*
456 * Global constants also used by locore.s
457 */
458
459struct cpu_functions cpufuncs;
460u_int cputype;
461#if __ARM_ARCH <= 5
462u_int cpu_reset_needs_v4_MMU_disable;	/* flag used in locore-v4.s */
463#endif
464
465#if defined(CPU_ARM9) ||	\
466  defined (CPU_ARM9E) ||	\
467  defined(CPU_ARM1176) ||	\
468  defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) ||		\
469  defined(CPU_FA526) || defined(CPU_MV_PJ4B) ||			\
470  defined(CPU_XSCALE_81342) || \
471  defined(CPU_CORTEXA) || defined(CPU_KRAIT)
472
473/* Global cache line sizes, use 32 as default */
474int	arm_dcache_min_line_size = 32;
475int	arm_icache_min_line_size = 32;
476int	arm_idcache_min_line_size = 32;
477
478static void get_cachetype_cp15(void);
479
480/* Additional cache information local to this file.  Log2 of some of the
481   above numbers.  */
482static int	arm_dcache_l2_nsets;
483static int	arm_dcache_l2_assoc;
484static int	arm_dcache_l2_linesize;
485
486static void
487get_cachetype_cp15(void)
488{
489	u_int ctype, isize, dsize, cpuid;
490	u_int clevel, csize, i, sel;
491	u_int multiplier;
492	u_char type;
493
494	__asm __volatile("mrc p15, 0, %0, c0, c0, 1"
495		: "=r" (ctype));
496
497	cpuid = cpu_ident();
498	/*
499	 * ...and thus spake the ARM ARM:
500	 *
501	 * If an <opcode2> value corresponding to an unimplemented or
502	 * reserved ID register is encountered, the System Control
503	 * processor returns the value of the main ID register.
504	 */
505	if (ctype == cpuid)
506		goto out;
507
508	if (CPU_CT_FORMAT(ctype) == CPU_CT_ARMV7) {
509		/* Resolve minimal cache line sizes */
510		arm_dcache_min_line_size = 1 << (CPU_CT_DMINLINE(ctype) + 2);
511		arm_icache_min_line_size = 1 << (CPU_CT_IMINLINE(ctype) + 2);
512		arm_idcache_min_line_size =
513		    min(arm_icache_min_line_size, arm_dcache_min_line_size);
514
515		__asm __volatile("mrc p15, 1, %0, c0, c0, 1"
516		    : "=r" (clevel));
517		arm_cache_level = clevel;
518		arm_cache_loc = CPU_CLIDR_LOC(arm_cache_level);
519		i = 0;
520		while ((type = (clevel & 0x7)) && i < 7) {
521			if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
522			    type == CACHE_SEP_CACHE) {
523				sel = i << 1;
524				__asm __volatile("mcr p15, 2, %0, c0, c0, 0"
525				    : : "r" (sel));
526				__asm __volatile("mrc p15, 1, %0, c0, c0, 0"
527				    : "=r" (csize));
528				arm_cache_type[sel] = csize;
529				arm_dcache_align = 1 <<
530				    (CPUV7_CT_xSIZE_LEN(csize) + 4);
531				arm_dcache_align_mask = arm_dcache_align - 1;
532			}
533			if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
534				sel = (i << 1) | 1;
535				__asm __volatile("mcr p15, 2, %0, c0, c0, 0"
536				    : : "r" (sel));
537				__asm __volatile("mrc p15, 1, %0, c0, c0, 0"
538				    : "=r" (csize));
539				arm_cache_type[sel] = csize;
540			}
541			i++;
542			clevel >>= 3;
543		}
544	} else {
545		if ((ctype & CPU_CT_S) == 0)
546			arm_pcache_unified = 1;
547
548		/*
549		 * If you want to know how this code works, go read the ARM ARM.
550		 */
551
552		arm_pcache_type = CPU_CT_CTYPE(ctype);
553
554		if (arm_pcache_unified == 0) {
555			isize = CPU_CT_ISIZE(ctype);
556			multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2;
557			arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3);
558			if (CPU_CT_xSIZE_ASSOC(isize) == 0) {
559				if (isize & CPU_CT_xSIZE_M)
560					arm_picache_line_size = 0; /* not present */
561				else
562					arm_picache_ways = 1;
563			} else {
564				arm_picache_ways = multiplier <<
565				    (CPU_CT_xSIZE_ASSOC(isize) - 1);
566			}
567			arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
568		}
569
570		dsize = CPU_CT_DSIZE(ctype);
571		multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
572		arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
573		if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
574			if (dsize & CPU_CT_xSIZE_M)
575				arm_pdcache_line_size = 0; /* not present */
576			else
577				arm_pdcache_ways = 1;
578		} else {
579			arm_pdcache_ways = multiplier <<
580			    (CPU_CT_xSIZE_ASSOC(dsize) - 1);
581		}
582		arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
583
584		arm_dcache_align = arm_pdcache_line_size;
585
586		arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2;
587		arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3;
588		arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) -
589		    CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize);
590
591	out:
592		arm_dcache_align_mask = arm_dcache_align - 1;
593	}
594}
595#endif /* ARM9 || XSCALE */
596
597/*
598 * Cannot panic here as we may not have a console yet ...
599 */
600
601int
602set_cpufuncs(void)
603{
604	cputype = cpu_ident();
605	cputype &= CPU_ID_CPU_MASK;
606
607#ifdef CPU_ARM9
608	if (((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD ||
609	     (cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_TI) &&
610	    (cputype & 0x0000f000) == 0x00009000) {
611		cpufuncs = arm9_cpufuncs;
612		cpu_reset_needs_v4_MMU_disable = 1;	/* V4 or higher */
613		get_cachetype_cp15();
614		arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize;
615		arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize +
616		    arm_dcache_l2_nsets)) - arm9_dcache_sets_inc;
617		arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc);
618		arm9_dcache_index_max = 0U - arm9_dcache_index_inc;
619		pmap_pte_init_generic();
620		goto out;
621	}
622#endif /* CPU_ARM9 */
623#if defined(CPU_ARM9E)
624	if (cputype == CPU_ID_MV88FR131 || cputype == CPU_ID_MV88FR571_VD ||
625	    cputype == CPU_ID_MV88FR571_41) {
626		uint32_t sheeva_ctrl;
627
628		sheeva_ctrl = (MV_DC_STREAM_ENABLE | MV_BTB_DISABLE |
629		    MV_L2_ENABLE);
630		/*
631		 * Workaround for Marvell MV78100 CPU: Cache prefetch
632		 * mechanism may affect the cache coherency validity,
633		 * so it needs to be disabled.
634		 *
635		 * Refer to errata document MV-S501058-00C.pdf (p. 3.1
636		 * L2 Prefetching Mechanism) for details.
637		 */
638		if (cputype == CPU_ID_MV88FR571_VD ||
639		    cputype == CPU_ID_MV88FR571_41)
640			sheeva_ctrl |= MV_L2_PREFETCH_DISABLE;
641
642		sheeva_control_ext(0xffffffff & ~MV_WA_ENABLE, sheeva_ctrl);
643
644		cpufuncs = sheeva_cpufuncs;
645		get_cachetype_cp15();
646		pmap_pte_init_generic();
647		goto out;
648	} else if (cputype == CPU_ID_ARM926EJS) {
649		cpufuncs = armv5_ec_cpufuncs;
650		get_cachetype_cp15();
651		pmap_pte_init_generic();
652		goto out;
653	}
654#endif /* CPU_ARM9E */
655#if defined(CPU_ARM1176)
656	if (cputype == CPU_ID_ARM1176JZS) {
657		cpufuncs = arm1176_cpufuncs;
658		get_cachetype_cp15();
659		goto out;
660	}
661#endif /* CPU_ARM1176 */
662#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
663	switch(cputype & CPU_ID_SCHEME_MASK) {
664	case CPU_ID_CORTEXA5:
665	case CPU_ID_CORTEXA7:
666	case CPU_ID_CORTEXA8:
667	case CPU_ID_CORTEXA9:
668	case CPU_ID_CORTEXA12:
669	case CPU_ID_CORTEXA15:
670	case CPU_ID_CORTEXA53:
671	case CPU_ID_CORTEXA57:
672	case CPU_ID_CORTEXA72:
673	case CPU_ID_KRAIT300:
674		cpufuncs = cortexa_cpufuncs;
675		get_cachetype_cp15();
676		goto out;
677	default:
678		break;
679	}
680#endif /* CPU_CORTEXA */
681
682#if defined(CPU_MV_PJ4B)
683	if (cputype == CPU_ID_MV88SV581X_V7 ||
684	    cputype == CPU_ID_MV88SV584X_V7 ||
685	    cputype == CPU_ID_ARM_88SV581X_V7) {
686		cpufuncs = pj4bv7_cpufuncs;
687		get_cachetype_cp15();
688		goto out;
689	}
690#endif /* CPU_MV_PJ4B */
691
692#if defined(CPU_FA526)
693	if (cputype == CPU_ID_FA526 || cputype == CPU_ID_FA626TE) {
694		cpufuncs = fa526_cpufuncs;
695		cpu_reset_needs_v4_MMU_disable = 1;	/* SA needs it	*/
696		get_cachetype_cp15();
697		pmap_pte_init_generic();
698
699		goto out;
700	}
701#endif	/* CPU_FA526 */
702
703#if defined(CPU_XSCALE_81342)
704	if (cputype == CPU_ID_81342) {
705		cpufuncs = xscalec3_cpufuncs;
706		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
707		get_cachetype_cp15();
708		pmap_pte_init_xscale();
709		goto out;
710	}
711#endif /* CPU_XSCALE_81342 */
712#ifdef CPU_XSCALE_PXA2X0
713	/* ignore core revision to test PXA2xx CPUs */
714	if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA250 ||
715	    (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X ||
716	    (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA210) {
717
718		cpufuncs = xscale_cpufuncs;
719		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
720		get_cachetype_cp15();
721		pmap_pte_init_xscale();
722
723		goto out;
724	}
725#endif /* CPU_XSCALE_PXA2X0 */
726#ifdef CPU_XSCALE_IXP425
727	if (cputype == CPU_ID_IXP425_533 || cputype == CPU_ID_IXP425_400 ||
728            cputype == CPU_ID_IXP425_266 || cputype == CPU_ID_IXP435) {
729
730		cpufuncs = xscale_cpufuncs;
731		cpu_reset_needs_v4_MMU_disable = 1;	/* XScale needs it */
732		get_cachetype_cp15();
733		pmap_pte_init_xscale();
734
735		goto out;
736	}
737#endif /* CPU_XSCALE_IXP425 */
738	/*
739	 * Bzzzz. And the answer was ...
740	 */
741	panic("No support for this CPU type (%08x) in kernel", cputype);
742	return(ARCHITECTURE_NOT_PRESENT);
743out:
744	uma_set_align(arm_dcache_align_mask);
745	return (0);
746}
747
748/*
749 * CPU Setup code
750 */
751
752#ifdef CPU_ARM9
753void
754arm9_setup(void)
755{
756	int cpuctrl, cpuctrlmask;
757
758	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
759	    | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
760	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
761	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE |
762	    CPU_CONTROL_ROUNDROBIN;
763	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
764		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
765		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
766		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
767		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
768		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_VECRELOC
769		 | CPU_CONTROL_ROUNDROBIN;
770
771#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
772	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
773#endif
774
775#ifdef __ARMEB__
776	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
777#endif
778	if (vector_page == ARM_VECTORS_HIGH)
779		cpuctrl |= CPU_CONTROL_VECRELOC;
780
781	/* Clear out the cache */
782	cpu_idcache_wbinv_all();
783
784	/* Set the control register (SCTLR)   */
785	cpu_control(cpuctrlmask, cpuctrl);
786
787}
788#endif	/* CPU_ARM9 */
789
790#if defined(CPU_ARM9E)
791void
792arm10_setup(void)
793{
794	int cpuctrl, cpuctrlmask;
795
796	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
797	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
798	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE;
799	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
800	    | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
801	    | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
802	    | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
803	    | CPU_CONTROL_BPRD_ENABLE
804	    | CPU_CONTROL_ROUNDROBIN | CPU_CONTROL_CPCLK;
805
806#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
807	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
808#endif
809
810#ifdef __ARMEB__
811	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
812#endif
813
814	/* Clear out the cache */
815	cpu_idcache_wbinv_all();
816
817	/* Now really make sure they are clean.  */
818	__asm __volatile ("mcr\tp15, 0, r0, c7, c7, 0" : : );
819
820	if (vector_page == ARM_VECTORS_HIGH)
821		cpuctrl |= CPU_CONTROL_VECRELOC;
822
823	/* Set the control register */
824	cpu_control(0xffffffff, cpuctrl);
825
826	/* And again. */
827	cpu_idcache_wbinv_all();
828}
829#endif	/* CPU_ARM9E || CPU_ARM10 */
830
831#if defined(CPU_ARM1176) \
832 || defined(CPU_MV_PJ4B) \
833 || defined(CPU_CORTEXA) || defined(CPU_KRAIT)
834static __inline void
835cpu_scc_setup_ccnt(void)
836{
837/* This is how you give userland access to the CCNT and PMCn
838 * registers.
839 * BEWARE! This gives write access also, which may not be what
840 * you want!
841 */
842#ifdef _PMC_USER_READ_WRITE_
843	/* Set PMUSERENR[0] to allow userland access */
844	cp15_pmuserenr_set(1);
845#endif
846#if defined(CPU_ARM1176)
847	/* Set PMCR[2,0] to enable counters and reset CCNT */
848	cp15_pmcr_set(5);
849#else
850	/* Set up the PMCCNTR register as a cyclecounter:
851	 * Set PMINTENCLR to 0xFFFFFFFF to block interrupts
852	 * Set PMCR[2,0] to enable counters and reset CCNT
853	 * Set PMCNTENSET to 0x80000000 to enable CCNT */
854	cp15_pminten_clr(0xFFFFFFFF);
855	cp15_pmcr_set(5);
856	cp15_pmcnten_set(0x80000000);
857#endif
858}
859#endif
860
861#if defined(CPU_ARM1176)
862void
863arm11x6_setup(void)
864{
865	uint32_t auxctrl, auxctrl_wax;
866	uint32_t tmp, tmp2;
867	uint32_t cpuid;
868
869	cpuid = cpu_ident();
870
871	auxctrl = 0;
872	auxctrl_wax = ~0;
873
874	/*
875	 * Enable an errata workaround
876	 */
877	if ((cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM1176JZS) { /* ARM1176JZSr0 */
878		auxctrl = ARM1176_AUXCTL_PHD;
879		auxctrl_wax = ~ARM1176_AUXCTL_PHD;
880	}
881
882	tmp = cp15_actlr_get();
883	tmp2 = tmp;
884	tmp &= auxctrl_wax;
885	tmp |= auxctrl;
886	if (tmp != tmp2)
887		cp15_actlr_set(tmp);
888
889	cpu_scc_setup_ccnt();
890}
891#endif  /* CPU_ARM1176 */
892
893#ifdef CPU_MV_PJ4B
894void
895pj4bv7_setup(void)
896{
897
898	pj4b_config();
899	cpu_scc_setup_ccnt();
900}
901#endif /* CPU_MV_PJ4B */
902
903#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
904
905void
906cortexa_setup(void)
907{
908
909	cpu_scc_setup_ccnt();
910}
911#endif  /* CPU_CORTEXA */
912
913#if defined(CPU_FA526)
914void
915fa526_setup(void)
916{
917	int cpuctrl, cpuctrlmask;
918
919	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
920		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
921		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
922		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
923		| CPU_CONTROL_BPRD_ENABLE;
924	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
925		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
926		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
927		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
928		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
929		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
930		 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC;
931
932#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
933	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
934#endif
935
936#ifdef __ARMEB__
937	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
938#endif
939
940	if (vector_page == ARM_VECTORS_HIGH)
941		cpuctrl |= CPU_CONTROL_VECRELOC;
942
943	/* Clear out the cache */
944	cpu_idcache_wbinv_all();
945
946	/* Set the control register */
947	cpu_control(0xffffffff, cpuctrl);
948}
949#endif	/* CPU_FA526 */
950
951#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
952  defined(CPU_XSCALE_81342)
953void
954xscale_setup(void)
955{
956	uint32_t auxctl;
957	int cpuctrl, cpuctrlmask;
958
959	/*
960	 * The XScale Write Buffer is always enabled.  Our option
961	 * is to enable/disable coalescing.  Note that bits 6:3
962	 * must always be enabled.
963	 */
964
965	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
966		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
967		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
968		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
969		 | CPU_CONTROL_BPRD_ENABLE;
970	cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
971		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
972		 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
973		 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
974		 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
975		 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
976		 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC | \
977		 CPU_CONTROL_L2_ENABLE;
978
979#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
980	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
981#endif
982
983#ifdef __ARMEB__
984	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
985#endif
986
987	if (vector_page == ARM_VECTORS_HIGH)
988		cpuctrl |= CPU_CONTROL_VECRELOC;
989#ifdef CPU_XSCALE_CORE3
990	cpuctrl |= CPU_CONTROL_L2_ENABLE;
991#endif
992
993	/* Clear out the cache */
994	cpu_idcache_wbinv_all();
995
996	/*
997	 * Set the control register.  Note that bits 6:3 must always
998	 * be set to 1.
999	 */
1000/*	cpu_control(cpuctrlmask, cpuctrl);*/
1001	cpu_control(0xffffffff, cpuctrl);
1002
1003	/* Make sure write coalescing is turned on */
1004	__asm __volatile("mrc p15, 0, %0, c1, c0, 1"
1005		: "=r" (auxctl));
1006#ifdef XSCALE_NO_COALESCE_WRITES
1007	auxctl |= XSCALE_AUXCTL_K;
1008#else
1009	auxctl &= ~XSCALE_AUXCTL_K;
1010#endif
1011#ifdef CPU_XSCALE_CORE3
1012	auxctl |= XSCALE_AUXCTL_LLR;
1013	auxctl |= XSCALE_AUXCTL_MD_MASK;
1014#endif
1015	__asm __volatile("mcr p15, 0, %0, c1, c0, 1"
1016		: : "r" (auxctl));
1017}
1018#endif	/* CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */
1019