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$");
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 */
72 int arm_picache_size;
73 int arm_picache_line_size;
74 int arm_picache_ways;
75
76 int arm_pdcache_size; /* and unified */
77 int arm_pdcache_line_size;
78 int arm_pdcache_ways;
79
80 int arm_pcache_type;
81 int arm_pcache_unified;
82
83 int arm_dcache_align;
84 int arm_dcache_align_mask;
85
86 u_int arm_cache_level;
87 u_int arm_cache_type[14];
88 u_int arm_cache_loc;
89
90 #ifdef CPU_ARM9
91 struct 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)
142 struct 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
192 struct 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
243 struct 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
262 struct 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
313 struct 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)
364 struct 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)
415 struct 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)
433 struct 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
459 struct cpu_functions cpufuncs;
460 u_int cputype;
461 #if __ARM_ARCH <= 5
462 u_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 */
474 int arm_dcache_min_line_size = 32;
475 int arm_icache_min_line_size = 32;
476 int arm_idcache_min_line_size = 32;
477
478 static void get_cachetype_cp15(void);
479
480 /* Additional cache information local to this file. Log2 of some of the
481 above numbers. */
482 static int arm_dcache_l2_nsets;
483 static int arm_dcache_l2_assoc;
484 static int arm_dcache_l2_linesize;
485
486 static void
get_cachetype_cp15(void)487 get_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
601 int
set_cpufuncs(void)602 set_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);
743 out:
744 uma_set_align(arm_dcache_align_mask);
745 return (0);
746 }
747
748 /*
749 * CPU Setup code
750 */
751
752 #ifdef CPU_ARM9
753 void
arm9_setup(void)754 arm9_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)
791 void
arm10_setup(void)792 arm10_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)
834 static __inline void
cpu_scc_setup_ccnt(void)835 cpu_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)
862 void
arm11x6_setup(void)863 arm11x6_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
894 void
pj4bv7_setup(void)895 pj4bv7_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
905 void
cortexa_setup(void)906 cortexa_setup(void)
907 {
908
909 cpu_scc_setup_ccnt();
910 }
911 #endif /* CPU_CORTEXA */
912
913 #if defined(CPU_FA526)
914 void
fa526_setup(void)915 fa526_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)
953 void
xscale_setup(void)954 xscale_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