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/cpuconf.h>
61 #include <machine/cpufunc.h>
62
63 #if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219)
64 #include <arm/xscale/i80321/i80321reg.h>
65 #include <arm/xscale/i80321/i80321var.h>
66 #endif
67
68 /*
69 * Some definitions in i81342reg.h clash with i80321reg.h.
70 * This only happens for the LINT kernel. As it happens,
71 * we don't need anything from i81342reg.h that we already
72 * got from somewhere else during a LINT compile.
73 */
74 #if defined(CPU_XSCALE_81342) && !defined(COMPILING_LINT)
75 #include <arm/xscale/i8134x/i81342reg.h>
76 #endif
77
78 #ifdef CPU_XSCALE_IXP425
79 #include <arm/xscale/ixp425/ixp425reg.h>
80 #include <arm/xscale/ixp425/ixp425var.h>
81 #endif
82
83 /* PRIMARY CACHE VARIABLES */
84 int arm_picache_size;
85 int arm_picache_line_size;
86 int arm_picache_ways;
87
88 int arm_pdcache_size; /* and unified */
89 int arm_pdcache_line_size;
90 int arm_pdcache_ways;
91
92 int arm_pcache_type;
93 int arm_pcache_unified;
94
95 int arm_dcache_align;
96 int arm_dcache_align_mask;
97
98 u_int arm_cache_level;
99 u_int arm_cache_type[14];
100 u_int arm_cache_loc;
101
102 int ctrl;
103
104 #ifdef CPU_ARM9
105 struct cpu_functions arm9_cpufuncs = {
106 /* CPU functions */
107
108 cpufunc_id, /* id */
109 cpufunc_nullop, /* cpwait */
110
111 /* MMU functions */
112
113 cpufunc_control, /* control */
114 cpufunc_domains, /* Domain */
115 arm9_setttb, /* Setttb */
116 cpufunc_faultstatus, /* Faultstatus */
117 cpufunc_faultaddress, /* Faultaddress */
118
119 /* TLB functions */
120
121 armv4_tlb_flushID, /* tlb_flushID */
122 arm9_tlb_flushID_SE, /* tlb_flushID_SE */
123 armv4_tlb_flushI, /* tlb_flushI */
124 (void *)armv4_tlb_flushI, /* tlb_flushI_SE */
125 armv4_tlb_flushD, /* tlb_flushD */
126 armv4_tlb_flushD_SE, /* tlb_flushD_SE */
127
128 /* Cache operations */
129
130 arm9_icache_sync_all, /* icache_sync_all */
131 arm9_icache_sync_range, /* icache_sync_range */
132
133 arm9_dcache_wbinv_all, /* dcache_wbinv_all */
134 arm9_dcache_wbinv_range, /* dcache_wbinv_range */
135 arm9_dcache_inv_range, /* dcache_inv_range */
136 arm9_dcache_wb_range, /* dcache_wb_range */
137
138 armv4_idcache_inv_all, /* idcache_inv_all */
139 arm9_idcache_wbinv_all, /* idcache_wbinv_all */
140 arm9_idcache_wbinv_range, /* idcache_wbinv_range */
141 cpufunc_nullop, /* l2cache_wbinv_all */
142 (void *)cpufunc_nullop, /* l2cache_wbinv_range */
143 (void *)cpufunc_nullop, /* l2cache_inv_range */
144 (void *)cpufunc_nullop, /* l2cache_wb_range */
145 (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
146
147 /* Other functions */
148
149 cpufunc_nullop, /* flush_prefetchbuf */
150 armv4_drain_writebuf, /* drain_writebuf */
151 cpufunc_nullop, /* flush_brnchtgt_C */
152 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
153
154 (void *)cpufunc_nullop, /* sleep */
155
156 /* Soft functions */
157
158 cpufunc_null_fixup, /* dataabt_fixup */
159 cpufunc_null_fixup, /* prefetchabt_fixup */
160
161 arm9_context_switch, /* context_switch */
162
163 arm9_setup /* cpu setup */
164
165 };
166 #endif /* CPU_ARM9 */
167
168 #if defined(CPU_ARM9E)
169 struct cpu_functions armv5_ec_cpufuncs = {
170 /* CPU functions */
171
172 cpufunc_id, /* id */
173 cpufunc_nullop, /* cpwait */
174
175 /* MMU functions */
176
177 cpufunc_control, /* control */
178 cpufunc_domains, /* Domain */
179 armv5_ec_setttb, /* Setttb */
180 cpufunc_faultstatus, /* Faultstatus */
181 cpufunc_faultaddress, /* Faultaddress */
182
183 /* TLB functions */
184
185 armv4_tlb_flushID, /* tlb_flushID */
186 arm10_tlb_flushID_SE, /* tlb_flushID_SE */
187 armv4_tlb_flushI, /* tlb_flushI */
188 arm10_tlb_flushI_SE, /* tlb_flushI_SE */
189 armv4_tlb_flushD, /* tlb_flushD */
190 armv4_tlb_flushD_SE, /* tlb_flushD_SE */
191
192 /* Cache operations */
193
194 armv5_ec_icache_sync_all, /* icache_sync_all */
195 armv5_ec_icache_sync_range, /* icache_sync_range */
196
197 armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */
198 armv5_ec_dcache_wbinv_range, /* dcache_wbinv_range */
199 armv5_ec_dcache_inv_range, /* dcache_inv_range */
200 armv5_ec_dcache_wb_range, /* dcache_wb_range */
201
202 armv4_idcache_inv_all, /* idcache_inv_all */
203 armv5_ec_idcache_wbinv_all, /* idcache_wbinv_all */
204 armv5_ec_idcache_wbinv_range, /* idcache_wbinv_range */
205
206 cpufunc_nullop, /* l2cache_wbinv_all */
207 (void *)cpufunc_nullop, /* l2cache_wbinv_range */
208 (void *)cpufunc_nullop, /* l2cache_inv_range */
209 (void *)cpufunc_nullop, /* l2cache_wb_range */
210 (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
211
212 /* Other functions */
213
214 cpufunc_nullop, /* flush_prefetchbuf */
215 armv4_drain_writebuf, /* drain_writebuf */
216 cpufunc_nullop, /* flush_brnchtgt_C */
217 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
218
219 (void *)cpufunc_nullop, /* sleep */
220
221 /* Soft functions */
222
223 cpufunc_null_fixup, /* dataabt_fixup */
224 cpufunc_null_fixup, /* prefetchabt_fixup */
225
226 arm10_context_switch, /* context_switch */
227
228 arm10_setup /* cpu setup */
229
230 };
231
232 struct cpu_functions sheeva_cpufuncs = {
233 /* CPU functions */
234
235 cpufunc_id, /* id */
236 cpufunc_nullop, /* cpwait */
237
238 /* MMU functions */
239
240 cpufunc_control, /* control */
241 cpufunc_domains, /* Domain */
242 sheeva_setttb, /* Setttb */
243 cpufunc_faultstatus, /* Faultstatus */
244 cpufunc_faultaddress, /* Faultaddress */
245
246 /* TLB functions */
247
248 armv4_tlb_flushID, /* tlb_flushID */
249 arm10_tlb_flushID_SE, /* tlb_flushID_SE */
250 armv4_tlb_flushI, /* tlb_flushI */
251 arm10_tlb_flushI_SE, /* tlb_flushI_SE */
252 armv4_tlb_flushD, /* tlb_flushD */
253 armv4_tlb_flushD_SE, /* tlb_flushD_SE */
254
255 /* Cache operations */
256
257 armv5_ec_icache_sync_all, /* icache_sync_all */
258 armv5_ec_icache_sync_range, /* icache_sync_range */
259
260 armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */
261 sheeva_dcache_wbinv_range, /* dcache_wbinv_range */
262 sheeva_dcache_inv_range, /* dcache_inv_range */
263 sheeva_dcache_wb_range, /* dcache_wb_range */
264
265 armv4_idcache_inv_all, /* idcache_inv_all */
266 armv5_ec_idcache_wbinv_all, /* idcache_wbinv_all */
267 sheeva_idcache_wbinv_range, /* idcache_wbinv_all */
268
269 sheeva_l2cache_wbinv_all, /* l2cache_wbinv_all */
270 sheeva_l2cache_wbinv_range, /* l2cache_wbinv_range */
271 sheeva_l2cache_inv_range, /* l2cache_inv_range */
272 sheeva_l2cache_wb_range, /* l2cache_wb_range */
273 (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
274
275 /* Other functions */
276
277 cpufunc_nullop, /* flush_prefetchbuf */
278 armv4_drain_writebuf, /* drain_writebuf */
279 cpufunc_nullop, /* flush_brnchtgt_C */
280 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
281
282 sheeva_cpu_sleep, /* sleep */
283
284 /* Soft functions */
285
286 cpufunc_null_fixup, /* dataabt_fixup */
287 cpufunc_null_fixup, /* prefetchabt_fixup */
288
289 arm10_context_switch, /* context_switch */
290
291 arm10_setup /* cpu setup */
292 };
293 #endif /* CPU_ARM9E */
294
295 #ifdef CPU_MV_PJ4B
296 struct cpu_functions pj4bv7_cpufuncs = {
297 /* CPU functions */
298
299 cpufunc_id, /* id */
300 armv7_drain_writebuf, /* cpwait */
301
302 /* MMU functions */
303
304 cpufunc_control, /* control */
305 cpufunc_domains, /* Domain */
306 armv7_setttb, /* Setttb */
307 cpufunc_faultstatus, /* Faultstatus */
308 cpufunc_faultaddress, /* Faultaddress */
309
310 /* TLB functions */
311
312 armv7_tlb_flushID, /* tlb_flushID */
313 armv7_tlb_flushID_SE, /* tlb_flushID_SE */
314 armv7_tlb_flushID, /* tlb_flushI */
315 armv7_tlb_flushID_SE, /* tlb_flushI_SE */
316 armv7_tlb_flushID, /* tlb_flushD */
317 armv7_tlb_flushID_SE, /* tlb_flushD_SE */
318
319 /* Cache operations */
320 armv7_idcache_wbinv_all, /* icache_sync_all */
321 armv7_icache_sync_range, /* icache_sync_range */
322
323 armv7_dcache_wbinv_all, /* dcache_wbinv_all */
324 armv7_dcache_wbinv_range, /* dcache_wbinv_range */
325 armv7_dcache_inv_range, /* dcache_inv_range */
326 armv7_dcache_wb_range, /* dcache_wb_range */
327
328 armv7_idcache_inv_all, /* idcache_inv_all */
329 armv7_idcache_wbinv_all, /* idcache_wbinv_all */
330 armv7_idcache_wbinv_range, /* idcache_wbinv_all */
331
332 (void *)cpufunc_nullop, /* l2cache_wbinv_all */
333 (void *)cpufunc_nullop, /* l2cache_wbinv_range */
334 (void *)cpufunc_nullop, /* l2cache_inv_range */
335 (void *)cpufunc_nullop, /* l2cache_wb_range */
336 (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
337
338 /* Other functions */
339
340 cpufunc_nullop, /* flush_prefetchbuf */
341 armv7_drain_writebuf, /* drain_writebuf */
342 cpufunc_nullop, /* flush_brnchtgt_C */
343 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
344
345 (void *)cpufunc_nullop, /* sleep */
346
347 /* Soft functions */
348
349 cpufunc_null_fixup, /* dataabt_fixup */
350 cpufunc_null_fixup, /* prefetchabt_fixup */
351
352 armv7_context_switch, /* context_switch */
353
354 pj4bv7_setup /* cpu setup */
355 };
356 #endif /* CPU_MV_PJ4B */
357
358 #if defined(CPU_XSCALE_80321) || \
359 defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
360 defined(CPU_XSCALE_80219)
361
362 struct cpu_functions xscale_cpufuncs = {
363 /* CPU functions */
364
365 cpufunc_id, /* id */
366 xscale_cpwait, /* cpwait */
367
368 /* MMU functions */
369
370 xscale_control, /* control */
371 cpufunc_domains, /* domain */
372 xscale_setttb, /* setttb */
373 cpufunc_faultstatus, /* faultstatus */
374 cpufunc_faultaddress, /* faultaddress */
375
376 /* TLB functions */
377
378 armv4_tlb_flushID, /* tlb_flushID */
379 xscale_tlb_flushID_SE, /* tlb_flushID_SE */
380 armv4_tlb_flushI, /* tlb_flushI */
381 (void *)armv4_tlb_flushI, /* tlb_flushI_SE */
382 armv4_tlb_flushD, /* tlb_flushD */
383 armv4_tlb_flushD_SE, /* tlb_flushD_SE */
384
385 /* Cache operations */
386
387 xscale_cache_syncI, /* icache_sync_all */
388 xscale_cache_syncI_rng, /* icache_sync_range */
389
390 xscale_cache_purgeD, /* dcache_wbinv_all */
391 xscale_cache_purgeD_rng, /* dcache_wbinv_range */
392 xscale_cache_flushD_rng, /* dcache_inv_range */
393 xscale_cache_cleanD_rng, /* dcache_wb_range */
394
395 xscale_cache_flushID, /* idcache_inv_all */
396 xscale_cache_purgeID, /* idcache_wbinv_all */
397 xscale_cache_purgeID_rng, /* idcache_wbinv_range */
398 cpufunc_nullop, /* l2cache_wbinv_all */
399 (void *)cpufunc_nullop, /* l2cache_wbinv_range */
400 (void *)cpufunc_nullop, /* l2cache_inv_range */
401 (void *)cpufunc_nullop, /* l2cache_wb_range */
402 (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
403
404 /* Other functions */
405
406 cpufunc_nullop, /* flush_prefetchbuf */
407 armv4_drain_writebuf, /* drain_writebuf */
408 cpufunc_nullop, /* flush_brnchtgt_C */
409 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
410
411 xscale_cpu_sleep, /* sleep */
412
413 /* Soft functions */
414
415 cpufunc_null_fixup, /* dataabt_fixup */
416 cpufunc_null_fixup, /* prefetchabt_fixup */
417
418 xscale_context_switch, /* context_switch */
419
420 xscale_setup /* cpu setup */
421 };
422 #endif
423 /* CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425
424 CPU_XSCALE_80219 */
425
426 #ifdef CPU_XSCALE_81342
427 struct cpu_functions xscalec3_cpufuncs = {
428 /* CPU functions */
429
430 cpufunc_id, /* id */
431 xscale_cpwait, /* cpwait */
432
433 /* MMU functions */
434
435 xscale_control, /* control */
436 cpufunc_domains, /* domain */
437 xscalec3_setttb, /* setttb */
438 cpufunc_faultstatus, /* faultstatus */
439 cpufunc_faultaddress, /* faultaddress */
440
441 /* TLB functions */
442
443 armv4_tlb_flushID, /* tlb_flushID */
444 xscale_tlb_flushID_SE, /* tlb_flushID_SE */
445 armv4_tlb_flushI, /* tlb_flushI */
446 (void *)armv4_tlb_flushI, /* tlb_flushI_SE */
447 armv4_tlb_flushD, /* tlb_flushD */
448 armv4_tlb_flushD_SE, /* tlb_flushD_SE */
449
450 /* Cache operations */
451
452 xscalec3_cache_syncI, /* icache_sync_all */
453 xscalec3_cache_syncI_rng, /* icache_sync_range */
454
455 xscalec3_cache_purgeD, /* dcache_wbinv_all */
456 xscalec3_cache_purgeD_rng, /* dcache_wbinv_range */
457 xscale_cache_flushD_rng, /* dcache_inv_range */
458 xscalec3_cache_cleanD_rng, /* dcache_wb_range */
459
460 xscale_cache_flushID, /* idcache_inv_all */
461 xscalec3_cache_purgeID, /* idcache_wbinv_all */
462 xscalec3_cache_purgeID_rng, /* idcache_wbinv_range */
463 xscalec3_l2cache_purge, /* l2cache_wbinv_all */
464 xscalec3_l2cache_purge_rng, /* l2cache_wbinv_range */
465 xscalec3_l2cache_flush_rng, /* l2cache_inv_range */
466 xscalec3_l2cache_clean_rng, /* l2cache_wb_range */
467 (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
468
469 /* Other functions */
470
471 cpufunc_nullop, /* flush_prefetchbuf */
472 armv4_drain_writebuf, /* drain_writebuf */
473 cpufunc_nullop, /* flush_brnchtgt_C */
474 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
475
476 xscale_cpu_sleep, /* sleep */
477
478 /* Soft functions */
479
480 cpufunc_null_fixup, /* dataabt_fixup */
481 cpufunc_null_fixup, /* prefetchabt_fixup */
482
483 xscalec3_context_switch, /* context_switch */
484
485 xscale_setup /* cpu setup */
486 };
487 #endif /* CPU_XSCALE_81342 */
488
489
490 #if defined(CPU_FA526)
491 struct cpu_functions fa526_cpufuncs = {
492 /* CPU functions */
493
494 cpufunc_id, /* id */
495 cpufunc_nullop, /* cpwait */
496
497 /* MMU functions */
498
499 cpufunc_control, /* control */
500 cpufunc_domains, /* domain */
501 fa526_setttb, /* setttb */
502 cpufunc_faultstatus, /* faultstatus */
503 cpufunc_faultaddress, /* faultaddress */
504
505 /* TLB functions */
506
507 armv4_tlb_flushID, /* tlb_flushID */
508 fa526_tlb_flushID_SE, /* tlb_flushID_SE */
509 armv4_tlb_flushI, /* tlb_flushI */
510 fa526_tlb_flushI_SE, /* tlb_flushI_SE */
511 armv4_tlb_flushD, /* tlb_flushD */
512 armv4_tlb_flushD_SE, /* tlb_flushD_SE */
513
514 /* Cache operations */
515
516 fa526_icache_sync_all, /* icache_sync_all */
517 fa526_icache_sync_range, /* icache_sync_range */
518
519 fa526_dcache_wbinv_all, /* dcache_wbinv_all */
520 fa526_dcache_wbinv_range, /* dcache_wbinv_range */
521 fa526_dcache_inv_range, /* dcache_inv_range */
522 fa526_dcache_wb_range, /* dcache_wb_range */
523
524 armv4_idcache_inv_all, /* idcache_inv_all */
525 fa526_idcache_wbinv_all, /* idcache_wbinv_all */
526 fa526_idcache_wbinv_range, /* idcache_wbinv_range */
527 cpufunc_nullop, /* l2cache_wbinv_all */
528 (void *)cpufunc_nullop, /* l2cache_wbinv_range */
529 (void *)cpufunc_nullop, /* l2cache_inv_range */
530 (void *)cpufunc_nullop, /* l2cache_wb_range */
531 (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
532
533 /* Other functions */
534
535 fa526_flush_prefetchbuf, /* flush_prefetchbuf */
536 armv4_drain_writebuf, /* drain_writebuf */
537 cpufunc_nullop, /* flush_brnchtgt_C */
538 fa526_flush_brnchtgt_E, /* flush_brnchtgt_E */
539
540 fa526_cpu_sleep, /* sleep */
541
542 /* Soft functions */
543
544 cpufunc_null_fixup, /* dataabt_fixup */
545 cpufunc_null_fixup, /* prefetchabt_fixup */
546
547 fa526_context_switch, /* context_switch */
548
549 fa526_setup /* cpu setup */
550 };
551 #endif /* CPU_FA526 */
552
553 #if defined(CPU_ARM1176)
554 struct cpu_functions arm1176_cpufuncs = {
555 /* CPU functions */
556
557 cpufunc_id, /* id */
558 cpufunc_nullop, /* cpwait */
559
560 /* MMU functions */
561
562 cpufunc_control, /* control */
563 cpufunc_domains, /* Domain */
564 arm11x6_setttb, /* Setttb */
565 cpufunc_faultstatus, /* Faultstatus */
566 cpufunc_faultaddress, /* Faultaddress */
567
568 /* TLB functions */
569
570 arm11_tlb_flushID, /* tlb_flushID */
571 arm11_tlb_flushID_SE, /* tlb_flushID_SE */
572 arm11_tlb_flushI, /* tlb_flushI */
573 arm11_tlb_flushI_SE, /* tlb_flushI_SE */
574 arm11_tlb_flushD, /* tlb_flushD */
575 arm11_tlb_flushD_SE, /* tlb_flushD_SE */
576
577 /* Cache operations */
578
579 arm11x6_icache_sync_all, /* icache_sync_all */
580 arm11x6_icache_sync_range, /* icache_sync_range */
581
582 arm11x6_dcache_wbinv_all, /* dcache_wbinv_all */
583 armv6_dcache_wbinv_range, /* dcache_wbinv_range */
584 armv6_dcache_inv_range, /* dcache_inv_range */
585 armv6_dcache_wb_range, /* dcache_wb_range */
586
587 armv6_idcache_inv_all, /* idcache_inv_all */
588 arm11x6_idcache_wbinv_all, /* idcache_wbinv_all */
589 arm11x6_idcache_wbinv_range, /* idcache_wbinv_range */
590
591 (void *)cpufunc_nullop, /* l2cache_wbinv_all */
592 (void *)cpufunc_nullop, /* l2cache_wbinv_range */
593 (void *)cpufunc_nullop, /* l2cache_inv_range */
594 (void *)cpufunc_nullop, /* l2cache_wb_range */
595 (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
596
597 /* Other functions */
598
599 arm11x6_flush_prefetchbuf, /* flush_prefetchbuf */
600 arm11_drain_writebuf, /* drain_writebuf */
601 cpufunc_nullop, /* flush_brnchtgt_C */
602 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
603
604 arm11x6_sleep, /* sleep */
605
606 /* Soft functions */
607
608 cpufunc_null_fixup, /* dataabt_fixup */
609 cpufunc_null_fixup, /* prefetchabt_fixup */
610
611 arm11_context_switch, /* context_switch */
612
613 arm11x6_setup /* cpu setup */
614 };
615 #endif /*CPU_ARM1176 */
616
617 #if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
618 struct cpu_functions cortexa_cpufuncs = {
619 /* CPU functions */
620
621 cpufunc_id, /* id */
622 cpufunc_nullop, /* cpwait */
623
624 /* MMU functions */
625
626 cpufunc_control, /* control */
627 cpufunc_domains, /* Domain */
628 armv7_setttb, /* Setttb */
629 cpufunc_faultstatus, /* Faultstatus */
630 cpufunc_faultaddress, /* Faultaddress */
631
632 /*
633 * TLB functions. ARMv7 does all TLB ops based on a unified TLB model
634 * whether the hardware implements separate I+D or not, so we use the
635 * same 'ID' functions for all 3 variations.
636 */
637
638 armv7_tlb_flushID, /* tlb_flushID */
639 armv7_tlb_flushID_SE, /* tlb_flushID_SE */
640 armv7_tlb_flushID, /* tlb_flushI */
641 armv7_tlb_flushID_SE, /* tlb_flushI_SE */
642 armv7_tlb_flushID, /* tlb_flushD */
643 armv7_tlb_flushID_SE, /* tlb_flushD_SE */
644
645 /* Cache operations */
646
647 armv7_icache_sync_all, /* icache_sync_all */
648 armv7_icache_sync_range, /* icache_sync_range */
649
650 armv7_dcache_wbinv_all, /* dcache_wbinv_all */
651 armv7_dcache_wbinv_range, /* dcache_wbinv_range */
652 armv7_dcache_inv_range, /* dcache_inv_range */
653 armv7_dcache_wb_range, /* dcache_wb_range */
654
655 armv7_idcache_inv_all, /* idcache_inv_all */
656 armv7_idcache_wbinv_all, /* idcache_wbinv_all */
657 armv7_idcache_wbinv_range, /* idcache_wbinv_range */
658
659 /*
660 * Note: For CPUs using the PL310 the L2 ops are filled in when the
661 * L2 cache controller is actually enabled.
662 */
663 cpufunc_nullop, /* l2cache_wbinv_all */
664 (void *)cpufunc_nullop, /* l2cache_wbinv_range */
665 (void *)cpufunc_nullop, /* l2cache_inv_range */
666 (void *)cpufunc_nullop, /* l2cache_wb_range */
667 (void *)cpufunc_nullop, /* l2cache_drain_writebuf */
668
669 /* Other functions */
670
671 cpufunc_nullop, /* flush_prefetchbuf */
672 armv7_drain_writebuf, /* drain_writebuf */
673 cpufunc_nullop, /* flush_brnchtgt_C */
674 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
675
676 armv7_cpu_sleep, /* sleep */
677
678 /* Soft functions */
679
680 cpufunc_null_fixup, /* dataabt_fixup */
681 cpufunc_null_fixup, /* prefetchabt_fixup */
682
683 armv7_context_switch, /* context_switch */
684
685 cortexa_setup /* cpu setup */
686 };
687 #endif /* CPU_CORTEXA */
688
689 /*
690 * Global constants also used by locore.s
691 */
692
693 struct cpu_functions cpufuncs;
694 u_int cputype;
695 u_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore.s */
696
697 #if defined(CPU_ARM9) || \
698 defined (CPU_ARM9E) || \
699 defined(CPU_ARM1176) || defined(CPU_XSCALE_80321) || \
700 defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
701 defined(CPU_FA526) || defined(CPU_MV_PJ4B) || \
702 defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \
703 defined(CPU_CORTEXA) || defined(CPU_KRAIT)
704
705 /* Global cache line sizes, use 32 as default */
706 int arm_dcache_min_line_size = 32;
707 int arm_icache_min_line_size = 32;
708 int arm_idcache_min_line_size = 32;
709
710 static void get_cachetype_cp15(void);
711
712 /* Additional cache information local to this file. Log2 of some of the
713 above numbers. */
714 static int arm_dcache_l2_nsets;
715 static int arm_dcache_l2_assoc;
716 static int arm_dcache_l2_linesize;
717
718 static void
get_cachetype_cp15()719 get_cachetype_cp15()
720 {
721 u_int ctype, isize, dsize, cpuid;
722 u_int clevel, csize, i, sel;
723 u_int multiplier;
724 u_char type;
725
726 __asm __volatile("mrc p15, 0, %0, c0, c0, 1"
727 : "=r" (ctype));
728
729 cpuid = cpufunc_id();
730 /*
731 * ...and thus spake the ARM ARM:
732 *
733 * If an <opcode2> value corresponding to an unimplemented or
734 * reserved ID register is encountered, the System Control
735 * processor returns the value of the main ID register.
736 */
737 if (ctype == cpuid)
738 goto out;
739
740 if (CPU_CT_FORMAT(ctype) == CPU_CT_ARMV7) {
741 /* Resolve minimal cache line sizes */
742 arm_dcache_min_line_size = 1 << (CPU_CT_DMINLINE(ctype) + 2);
743 arm_icache_min_line_size = 1 << (CPU_CT_IMINLINE(ctype) + 2);
744 arm_idcache_min_line_size =
745 min(arm_icache_min_line_size, arm_dcache_min_line_size);
746
747 __asm __volatile("mrc p15, 1, %0, c0, c0, 1"
748 : "=r" (clevel));
749 arm_cache_level = clevel;
750 arm_cache_loc = CPU_CLIDR_LOC(arm_cache_level);
751 i = 0;
752 while ((type = (clevel & 0x7)) && i < 7) {
753 if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
754 type == CACHE_SEP_CACHE) {
755 sel = i << 1;
756 __asm __volatile("mcr p15, 2, %0, c0, c0, 0"
757 : : "r" (sel));
758 __asm __volatile("mrc p15, 1, %0, c0, c0, 0"
759 : "=r" (csize));
760 arm_cache_type[sel] = csize;
761 arm_dcache_align = 1 <<
762 (CPUV7_CT_xSIZE_LEN(csize) + 4);
763 arm_dcache_align_mask = arm_dcache_align - 1;
764 }
765 if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
766 sel = (i << 1) | 1;
767 __asm __volatile("mcr p15, 2, %0, c0, c0, 0"
768 : : "r" (sel));
769 __asm __volatile("mrc p15, 1, %0, c0, c0, 0"
770 : "=r" (csize));
771 arm_cache_type[sel] = csize;
772 }
773 i++;
774 clevel >>= 3;
775 }
776 } else {
777 if ((ctype & CPU_CT_S) == 0)
778 arm_pcache_unified = 1;
779
780 /*
781 * If you want to know how this code works, go read the ARM ARM.
782 */
783
784 arm_pcache_type = CPU_CT_CTYPE(ctype);
785
786 if (arm_pcache_unified == 0) {
787 isize = CPU_CT_ISIZE(ctype);
788 multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2;
789 arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3);
790 if (CPU_CT_xSIZE_ASSOC(isize) == 0) {
791 if (isize & CPU_CT_xSIZE_M)
792 arm_picache_line_size = 0; /* not present */
793 else
794 arm_picache_ways = 1;
795 } else {
796 arm_picache_ways = multiplier <<
797 (CPU_CT_xSIZE_ASSOC(isize) - 1);
798 }
799 arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
800 }
801
802 dsize = CPU_CT_DSIZE(ctype);
803 multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
804 arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
805 if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
806 if (dsize & CPU_CT_xSIZE_M)
807 arm_pdcache_line_size = 0; /* not present */
808 else
809 arm_pdcache_ways = 1;
810 } else {
811 arm_pdcache_ways = multiplier <<
812 (CPU_CT_xSIZE_ASSOC(dsize) - 1);
813 }
814 arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
815
816 arm_dcache_align = arm_pdcache_line_size;
817
818 arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2;
819 arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3;
820 arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) -
821 CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize);
822
823 out:
824 arm_dcache_align_mask = arm_dcache_align - 1;
825 }
826 }
827 #endif /* ARM9 || XSCALE */
828
829 /*
830 * Cannot panic here as we may not have a console yet ...
831 */
832
833 int
set_cpufuncs()834 set_cpufuncs()
835 {
836 cputype = cpufunc_id();
837 cputype &= CPU_ID_CPU_MASK;
838
839 #ifdef CPU_ARM9
840 if (((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD ||
841 (cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_TI) &&
842 (cputype & 0x0000f000) == 0x00009000) {
843 cpufuncs = arm9_cpufuncs;
844 cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */
845 get_cachetype_cp15();
846 arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize;
847 arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize +
848 arm_dcache_l2_nsets)) - arm9_dcache_sets_inc;
849 arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc);
850 arm9_dcache_index_max = 0U - arm9_dcache_index_inc;
851 pmap_pte_init_generic();
852 goto out;
853 }
854 #endif /* CPU_ARM9 */
855 #if defined(CPU_ARM9E)
856 if (cputype == CPU_ID_MV88FR131 || cputype == CPU_ID_MV88FR571_VD ||
857 cputype == CPU_ID_MV88FR571_41) {
858 uint32_t sheeva_ctrl;
859
860 sheeva_ctrl = (MV_DC_STREAM_ENABLE | MV_BTB_DISABLE |
861 MV_L2_ENABLE);
862 /*
863 * Workaround for Marvell MV78100 CPU: Cache prefetch
864 * mechanism may affect the cache coherency validity,
865 * so it needs to be disabled.
866 *
867 * Refer to errata document MV-S501058-00C.pdf (p. 3.1
868 * L2 Prefetching Mechanism) for details.
869 */
870 if (cputype == CPU_ID_MV88FR571_VD ||
871 cputype == CPU_ID_MV88FR571_41)
872 sheeva_ctrl |= MV_L2_PREFETCH_DISABLE;
873
874 sheeva_control_ext(0xffffffff & ~MV_WA_ENABLE, sheeva_ctrl);
875
876 cpufuncs = sheeva_cpufuncs;
877 get_cachetype_cp15();
878 pmap_pte_init_generic();
879 goto out;
880 } else if (cputype == CPU_ID_ARM926EJS) {
881 cpufuncs = armv5_ec_cpufuncs;
882 get_cachetype_cp15();
883 pmap_pte_init_generic();
884 goto out;
885 }
886 #endif /* CPU_ARM9E */
887 #if defined(CPU_ARM1176)
888 if (cputype == CPU_ID_ARM1176JZS) {
889 cpufuncs = arm1176_cpufuncs;
890 cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */
891 get_cachetype_cp15();
892
893 pmap_pte_init_mmu_v6();
894
895 goto out;
896 }
897 #endif /* CPU_ARM1176 */
898 #if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
899 if (cputype == CPU_ID_CORTEXA5 ||
900 cputype == CPU_ID_CORTEXA7 ||
901 cputype == CPU_ID_CORTEXA8R1 ||
902 cputype == CPU_ID_CORTEXA8R2 ||
903 cputype == CPU_ID_CORTEXA8R3 ||
904 cputype == CPU_ID_CORTEXA9R1 ||
905 cputype == CPU_ID_CORTEXA9R2 ||
906 cputype == CPU_ID_CORTEXA9R3 ||
907 cputype == CPU_ID_CORTEXA9R4 ||
908 cputype == CPU_ID_CORTEXA12R0 ||
909 cputype == CPU_ID_CORTEXA15R0 ||
910 cputype == CPU_ID_CORTEXA15R1 ||
911 cputype == CPU_ID_CORTEXA15R2 ||
912 cputype == CPU_ID_CORTEXA15R3 ||
913 cputype == CPU_ID_KRAIT300R0 ||
914 cputype == CPU_ID_KRAIT300R1 ) {
915 cpufuncs = cortexa_cpufuncs;
916 cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */
917 get_cachetype_cp15();
918
919 pmap_pte_init_mmu_v6();
920 goto out;
921 }
922 #endif /* CPU_CORTEXA */
923
924 #if defined(CPU_MV_PJ4B)
925 if (cputype == CPU_ID_MV88SV581X_V7 ||
926 cputype == CPU_ID_MV88SV584X_V7 ||
927 cputype == CPU_ID_ARM_88SV581X_V7) {
928 cpufuncs = pj4bv7_cpufuncs;
929 get_cachetype_cp15();
930 pmap_pte_init_mmu_v6();
931 goto out;
932 }
933 #endif /* CPU_MV_PJ4B */
934
935 #if defined(CPU_FA526)
936 if (cputype == CPU_ID_FA526 || cputype == CPU_ID_FA626TE) {
937 cpufuncs = fa526_cpufuncs;
938 cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */
939 get_cachetype_cp15();
940 pmap_pte_init_generic();
941
942 goto out;
943 }
944 #endif /* CPU_FA526 */
945
946 #if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219)
947 if (cputype == CPU_ID_80321_400 || cputype == CPU_ID_80321_600 ||
948 cputype == CPU_ID_80321_400_B0 || cputype == CPU_ID_80321_600_B0 ||
949 cputype == CPU_ID_80219_400 || cputype == CPU_ID_80219_600) {
950 cpufuncs = xscale_cpufuncs;
951 cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */
952 get_cachetype_cp15();
953 pmap_pte_init_xscale();
954 goto out;
955 }
956 #endif /* CPU_XSCALE_80321 */
957
958 #if defined(CPU_XSCALE_81342)
959 if (cputype == CPU_ID_81342) {
960 cpufuncs = xscalec3_cpufuncs;
961 cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */
962 get_cachetype_cp15();
963 pmap_pte_init_xscale();
964 goto out;
965 }
966 #endif /* CPU_XSCALE_81342 */
967 #ifdef CPU_XSCALE_PXA2X0
968 /* ignore core revision to test PXA2xx CPUs */
969 if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA250 ||
970 (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X ||
971 (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA210) {
972
973 cpufuncs = xscale_cpufuncs;
974 cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */
975 get_cachetype_cp15();
976 pmap_pte_init_xscale();
977
978 goto out;
979 }
980 #endif /* CPU_XSCALE_PXA2X0 */
981 #ifdef CPU_XSCALE_IXP425
982 if (cputype == CPU_ID_IXP425_533 || cputype == CPU_ID_IXP425_400 ||
983 cputype == CPU_ID_IXP425_266 || cputype == CPU_ID_IXP435) {
984
985 cpufuncs = xscale_cpufuncs;
986 cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */
987 get_cachetype_cp15();
988 pmap_pte_init_xscale();
989
990 goto out;
991 }
992 #endif /* CPU_XSCALE_IXP425 */
993 /*
994 * Bzzzz. And the answer was ...
995 */
996 panic("No support for this CPU type (%08x) in kernel", cputype);
997 return(ARCHITECTURE_NOT_PRESENT);
998 out:
999 uma_set_align(arm_dcache_align_mask);
1000 return (0);
1001 }
1002
1003 /*
1004 * Fixup routines for data and prefetch aborts.
1005 *
1006 * Several compile time symbols are used
1007 *
1008 * DEBUG_FAULT_CORRECTION - Print debugging information during the
1009 * correction of registers after a fault.
1010 */
1011
1012
1013 /*
1014 * Null abort fixup routine.
1015 * For use when no fixup is required.
1016 */
1017 int
cpufunc_null_fixup(arg)1018 cpufunc_null_fixup(arg)
1019 void *arg;
1020 {
1021 return(ABORT_FIXUP_OK);
1022 }
1023
1024 /*
1025 * CPU Setup code
1026 */
1027
1028 #ifdef CPU_ARM9
1029 void
arm9_setup(void)1030 arm9_setup(void)
1031 {
1032 int cpuctrl, cpuctrlmask;
1033
1034 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1035 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1036 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1037 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE |
1038 CPU_CONTROL_ROUNDROBIN;
1039 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1040 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1041 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1042 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
1043 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
1044 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_VECRELOC
1045 | CPU_CONTROL_ROUNDROBIN;
1046
1047 #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1048 cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1049 #endif
1050
1051 #ifdef __ARMEB__
1052 cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1053 #endif
1054 if (vector_page == ARM_VECTORS_HIGH)
1055 cpuctrl |= CPU_CONTROL_VECRELOC;
1056
1057 /* Clear out the cache */
1058 cpu_idcache_wbinv_all();
1059
1060 /* Set the control register */
1061 cpu_control(cpuctrlmask, cpuctrl);
1062 ctrl = cpuctrl;
1063
1064 }
1065 #endif /* CPU_ARM9 */
1066
1067 #if defined(CPU_ARM9E)
1068 void
arm10_setup(void)1069 arm10_setup(void)
1070 {
1071 int cpuctrl, cpuctrlmask;
1072
1073 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
1074 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1075 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE;
1076 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
1077 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1078 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
1079 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
1080 | CPU_CONTROL_BPRD_ENABLE
1081 | CPU_CONTROL_ROUNDROBIN | CPU_CONTROL_CPCLK;
1082
1083 #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1084 cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1085 #endif
1086
1087 #ifdef __ARMEB__
1088 cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1089 #endif
1090
1091 /* Clear out the cache */
1092 cpu_idcache_wbinv_all();
1093
1094 /* Now really make sure they are clean. */
1095 __asm __volatile ("mcr\tp15, 0, r0, c7, c7, 0" : : );
1096
1097 if (vector_page == ARM_VECTORS_HIGH)
1098 cpuctrl |= CPU_CONTROL_VECRELOC;
1099
1100 /* Set the control register */
1101 ctrl = cpuctrl;
1102 cpu_control(0xffffffff, cpuctrl);
1103
1104 /* And again. */
1105 cpu_idcache_wbinv_all();
1106 }
1107 #endif /* CPU_ARM9E || CPU_ARM10 */
1108
1109 #if defined(CPU_ARM1176) \
1110 || defined(CPU_MV_PJ4B) \
1111 || defined(CPU_CORTEXA) || defined(CPU_KRAIT)
1112 static __inline void
cpu_scc_setup_ccnt(void)1113 cpu_scc_setup_ccnt(void)
1114 {
1115 /* This is how you give userland access to the CCNT and PMCn
1116 * registers.
1117 * BEWARE! This gives write access also, which may not be what
1118 * you want!
1119 */
1120 #ifdef _PMC_USER_READ_WRITE_
1121 /* Set PMUSERENR[0] to allow userland access */
1122 cp15_pmuserenr_set(1);
1123 #endif
1124 #if defined(CPU_ARM1176)
1125 /* Set PMCR[2,0] to enable counters and reset CCNT */
1126 cp15_pmcr_set(5);
1127 #else
1128 /* Set up the PMCCNTR register as a cyclecounter:
1129 * Set PMINTENCLR to 0xFFFFFFFF to block interrupts
1130 * Set PMCR[2,0] to enable counters and reset CCNT
1131 * Set PMCNTENSET to 0x80000000 to enable CCNT */
1132 cp15_pminten_clr(0xFFFFFFFF);
1133 cp15_pmcr_set(5);
1134 cp15_pmcnten_set(0x80000000);
1135 #endif
1136 }
1137 #endif
1138
1139 #if defined(CPU_ARM1176)
1140 void
arm11x6_setup(void)1141 arm11x6_setup(void)
1142 {
1143 int cpuctrl, cpuctrl_wax;
1144 uint32_t auxctrl, auxctrl_wax;
1145 uint32_t tmp, tmp2;
1146 uint32_t sbz=0;
1147 uint32_t cpuid;
1148
1149 cpuid = cpufunc_id();
1150
1151 cpuctrl =
1152 CPU_CONTROL_MMU_ENABLE |
1153 CPU_CONTROL_DC_ENABLE |
1154 CPU_CONTROL_WBUF_ENABLE |
1155 CPU_CONTROL_32BP_ENABLE |
1156 CPU_CONTROL_32BD_ENABLE |
1157 CPU_CONTROL_LABT_ENABLE |
1158 CPU_CONTROL_SYST_ENABLE |
1159 CPU_CONTROL_IC_ENABLE |
1160 CPU_CONTROL_UNAL_ENABLE;
1161
1162 /*
1163 * "write as existing" bits
1164 * inverse of this is mask
1165 */
1166 cpuctrl_wax =
1167 (3 << 30) | /* SBZ */
1168 (1 << 29) | /* FA */
1169 (1 << 28) | /* TR */
1170 (3 << 26) | /* SBZ */
1171 (3 << 19) | /* SBZ */
1172 (1 << 17); /* SBZ */
1173
1174 cpuctrl |= CPU_CONTROL_BPRD_ENABLE;
1175 cpuctrl |= CPU_CONTROL_V6_EXTPAGE;
1176
1177 #ifdef __ARMEB__
1178 cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1179 #endif
1180
1181 if (vector_page == ARM_VECTORS_HIGH)
1182 cpuctrl |= CPU_CONTROL_VECRELOC;
1183
1184 auxctrl = 0;
1185 auxctrl_wax = ~0;
1186
1187 /*
1188 * Enable an errata workaround
1189 */
1190 if ((cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM1176JZS) { /* ARM1176JZSr0 */
1191 auxctrl = ARM1176_AUXCTL_PHD;
1192 auxctrl_wax = ~ARM1176_AUXCTL_PHD;
1193 }
1194
1195 /* Clear out the cache */
1196 cpu_idcache_wbinv_all();
1197
1198 /* Now really make sure they are clean. */
1199 __asm volatile ("mcr\tp15, 0, %0, c7, c7, 0" : : "r"(sbz));
1200
1201 /* Allow detection code to find the VFP if it's fitted. */
1202 cp15_cpacr_set(0x0fffffff);
1203
1204 /* Set the control register */
1205 ctrl = cpuctrl;
1206 cpu_control(~cpuctrl_wax, cpuctrl);
1207
1208 tmp = cp15_actlr_get();
1209 tmp2 = tmp;
1210 tmp &= auxctrl_wax;
1211 tmp |= auxctrl;
1212 if (tmp != tmp2)
1213 cp15_actlr_set(tmp);
1214
1215 /* And again. */
1216 cpu_idcache_wbinv_all();
1217
1218 cpu_scc_setup_ccnt();
1219 }
1220 #endif /* CPU_ARM1176 */
1221
1222 #ifdef CPU_MV_PJ4B
1223 void
pj4bv7_setup(void)1224 pj4bv7_setup(void)
1225 {
1226 int cpuctrl;
1227
1228 pj4b_config();
1229
1230 cpuctrl = CPU_CONTROL_MMU_ENABLE;
1231 #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1232 cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1233 #endif
1234 cpuctrl |= CPU_CONTROL_DC_ENABLE;
1235 cpuctrl |= (0xf << 3);
1236 cpuctrl |= CPU_CONTROL_BPRD_ENABLE;
1237 cpuctrl |= CPU_CONTROL_IC_ENABLE;
1238 if (vector_page == ARM_VECTORS_HIGH)
1239 cpuctrl |= CPU_CONTROL_VECRELOC;
1240 cpuctrl |= (0x5 << 16) | (1 < 22);
1241 cpuctrl |= CPU_CONTROL_V6_EXTPAGE;
1242
1243 /* Clear out the cache */
1244 cpu_idcache_wbinv_all();
1245
1246 /* Set the control register */
1247 ctrl = cpuctrl;
1248 cpu_control(0xFFFFFFFF, cpuctrl);
1249
1250 /* And again. */
1251 cpu_idcache_wbinv_all();
1252
1253 cpu_scc_setup_ccnt();
1254 }
1255 #endif /* CPU_MV_PJ4B */
1256
1257 #if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
1258
1259 void
cortexa_setup(void)1260 cortexa_setup(void)
1261 {
1262 int cpuctrl, cpuctrlmask;
1263
1264 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | /* MMU enable [0] */
1265 CPU_CONTROL_AFLT_ENABLE | /* Alignment fault [1] */
1266 CPU_CONTROL_DC_ENABLE | /* DCache enable [2] */
1267 CPU_CONTROL_BPRD_ENABLE | /* Branch prediction [11] */
1268 CPU_CONTROL_IC_ENABLE | /* ICache enable [12] */
1269 CPU_CONTROL_VECRELOC; /* Vector relocation [13] */
1270
1271 cpuctrl = CPU_CONTROL_MMU_ENABLE |
1272 CPU_CONTROL_IC_ENABLE |
1273 CPU_CONTROL_DC_ENABLE |
1274 CPU_CONTROL_BPRD_ENABLE;
1275
1276 #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1277 cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1278 #endif
1279
1280 /* Switch to big endian */
1281 #ifdef __ARMEB__
1282 cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1283 #endif
1284
1285 /* Check if the vector page is at the high address (0xffff0000) */
1286 if (vector_page == ARM_VECTORS_HIGH)
1287 cpuctrl |= CPU_CONTROL_VECRELOC;
1288
1289 /* Clear out the cache */
1290 cpu_idcache_wbinv_all();
1291
1292 /* Set the control register */
1293 ctrl = cpuctrl;
1294 cpu_control(cpuctrlmask, cpuctrl);
1295
1296 /* And again. */
1297 cpu_idcache_wbinv_all();
1298 #if defined(SMP) && !defined(ARM_NEW_PMAP)
1299 armv7_auxctrl((1 << 6) | (1 << 0), (1 << 6) | (1 << 0)); /* Enable SMP + TLB broadcasting */
1300 #endif
1301
1302 cpu_scc_setup_ccnt();
1303 }
1304 #endif /* CPU_CORTEXA */
1305
1306 #if defined(CPU_FA526)
1307 void
fa526_setup(void)1308 fa526_setup(void)
1309 {
1310 int cpuctrl, cpuctrlmask;
1311
1312 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1313 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1314 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1315 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
1316 | CPU_CONTROL_BPRD_ENABLE;
1317 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1318 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1319 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1320 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
1321 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
1322 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
1323 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC;
1324
1325 #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1326 cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1327 #endif
1328
1329 #ifdef __ARMEB__
1330 cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1331 #endif
1332
1333 if (vector_page == ARM_VECTORS_HIGH)
1334 cpuctrl |= CPU_CONTROL_VECRELOC;
1335
1336 /* Clear out the cache */
1337 cpu_idcache_wbinv_all();
1338
1339 /* Set the control register */
1340 ctrl = cpuctrl;
1341 cpu_control(0xffffffff, cpuctrl);
1342 }
1343 #endif /* CPU_FA526 */
1344
1345 #if defined(CPU_XSCALE_80321) || \
1346 defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
1347 defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)
1348 void
xscale_setup(void)1349 xscale_setup(void)
1350 {
1351 uint32_t auxctl;
1352 int cpuctrl, cpuctrlmask;
1353
1354 /*
1355 * The XScale Write Buffer is always enabled. Our option
1356 * is to enable/disable coalescing. Note that bits 6:3
1357 * must always be enabled.
1358 */
1359
1360 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1361 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1362 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1363 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
1364 | CPU_CONTROL_BPRD_ENABLE;
1365 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1366 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1367 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1368 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
1369 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
1370 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
1371 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC | \
1372 CPU_CONTROL_L2_ENABLE;
1373
1374 #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1375 cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1376 #endif
1377
1378 #ifdef __ARMEB__
1379 cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1380 #endif
1381
1382 if (vector_page == ARM_VECTORS_HIGH)
1383 cpuctrl |= CPU_CONTROL_VECRELOC;
1384 #ifdef CPU_XSCALE_CORE3
1385 cpuctrl |= CPU_CONTROL_L2_ENABLE;
1386 #endif
1387
1388 /* Clear out the cache */
1389 cpu_idcache_wbinv_all();
1390
1391 /*
1392 * Set the control register. Note that bits 6:3 must always
1393 * be set to 1.
1394 */
1395 ctrl = cpuctrl;
1396 /* cpu_control(cpuctrlmask, cpuctrl);*/
1397 cpu_control(0xffffffff, cpuctrl);
1398
1399 /* Make sure write coalescing is turned on */
1400 __asm __volatile("mrc p15, 0, %0, c1, c0, 1"
1401 : "=r" (auxctl));
1402 #ifdef XSCALE_NO_COALESCE_WRITES
1403 auxctl |= XSCALE_AUXCTL_K;
1404 #else
1405 auxctl &= ~XSCALE_AUXCTL_K;
1406 #endif
1407 #ifdef CPU_XSCALE_CORE3
1408 auxctl |= XSCALE_AUXCTL_LLR;
1409 auxctl |= XSCALE_AUXCTL_MD_MASK;
1410 #endif
1411 __asm __volatile("mcr p15, 0, %0, c1, c0, 1"
1412 : : "r" (auxctl));
1413 }
1414 #endif /* CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425
1415 CPU_XSCALE_80219 */
1416