FreeBSD/Linux Kernel Cross Reference
sys/arm/arm/cpufunc.c
1 /* $NetBSD: cpufunc.c,v 1.65 2003/11/05 12:53:15 scw Exp $ */
2
3 /*-
4 * arm7tdmi support code Copyright (c) 2001 John Fremlin
5 * arm8 support code Copyright (c) 1997 ARM Limited
6 * arm8 support code Copyright (c) 1997 Causality Limited
7 * arm9 support code Copyright (C) 2001 ARM Ltd
8 * Copyright (c) 1997 Mark Brinicombe.
9 * Copyright (c) 1997 Causality Limited
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by Causality Limited.
23 * 4. The name of Causality Limited may not be used to endorse or promote
24 * products derived from this software without specific prior written
25 * permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
28 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
30 * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
31 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * RiscBSD kernel project
40 *
41 * cpufuncs.c
42 *
43 * C functions for supporting CPU / MMU / TLB specific operations.
44 *
45 * Created : 30/01/97
46 */
47 #include <sys/cdefs.h>
48 __FBSDID("$FreeBSD: src/sys/arm/arm/cpufunc.c,v 1.24 2008/12/20 03:26:09 sam Exp $");
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/lock.h>
53 #include <sys/mutex.h>
54 #include <sys/bus.h>
55 #include <machine/bus.h>
56 #include <machine/cpu.h>
57 #include <machine/disassem.h>
58
59 #include <vm/vm.h>
60 #include <vm/pmap.h>
61 #include <vm/uma.h>
62
63 #include <machine/cpuconf.h>
64 #include <machine/cpufunc.h>
65 #include <machine/bootconfig.h>
66
67 #ifdef CPU_XSCALE_80200
68 #include <arm/xscale/i80200/i80200reg.h>
69 #include <arm/xscale/i80200/i80200var.h>
70 #endif
71
72 #if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219)
73 #include <arm/xscale/i80321/i80321reg.h>
74 #include <arm/xscale/i80321/i80321var.h>
75 #endif
76
77 #if defined(CPU_XSCALE_81342)
78 #include <arm/xscale/i8134x/i81342reg.h>
79 #endif
80
81 #ifdef CPU_XSCALE_IXP425
82 #include <arm/xscale/ixp425/ixp425reg.h>
83 #include <arm/xscale/ixp425/ixp425var.h>
84 #endif
85
86 #if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
87 defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)
88 #include <arm/xscale/xscalereg.h>
89 #endif
90
91 #if defined(PERFCTRS)
92 struct arm_pmc_funcs *arm_pmc;
93 #endif
94
95 /* PRIMARY CACHE VARIABLES */
96 int arm_picache_size;
97 int arm_picache_line_size;
98 int arm_picache_ways;
99
100 int arm_pdcache_size; /* and unified */
101 int arm_pdcache_line_size;
102 int arm_pdcache_ways;
103
104 int arm_pcache_type;
105 int arm_pcache_unified;
106
107 int arm_dcache_align;
108 int arm_dcache_align_mask;
109
110 /* 1 == use cpu_sleep(), 0 == don't */
111 int cpu_do_powersave;
112 int ctrl;
113
114 #ifdef CPU_ARM7TDMI
115 struct cpu_functions arm7tdmi_cpufuncs = {
116 /* CPU functions */
117
118 cpufunc_id, /* id */
119 cpufunc_nullop, /* cpwait */
120
121 /* MMU functions */
122
123 cpufunc_control, /* control */
124 cpufunc_domains, /* domain */
125 arm7tdmi_setttb, /* setttb */
126 cpufunc_faultstatus, /* faultstatus */
127 cpufunc_faultaddress, /* faultaddress */
128
129 /* TLB functions */
130
131 arm7tdmi_tlb_flushID, /* tlb_flushID */
132 arm7tdmi_tlb_flushID_SE, /* tlb_flushID_SE */
133 arm7tdmi_tlb_flushID, /* tlb_flushI */
134 arm7tdmi_tlb_flushID_SE, /* tlb_flushI_SE */
135 arm7tdmi_tlb_flushID, /* tlb_flushD */
136 arm7tdmi_tlb_flushID_SE, /* tlb_flushD_SE */
137
138 /* Cache operations */
139
140 cpufunc_nullop, /* icache_sync_all */
141 (void *)cpufunc_nullop, /* icache_sync_range */
142
143 arm7tdmi_cache_flushID, /* dcache_wbinv_all */
144 (void *)arm7tdmi_cache_flushID, /* dcache_wbinv_range */
145 (void *)arm7tdmi_cache_flushID, /* dcache_inv_range */
146 (void *)cpufunc_nullop, /* dcache_wb_range */
147
148 arm7tdmi_cache_flushID, /* idcache_wbinv_all */
149 (void *)arm7tdmi_cache_flushID, /* idcache_wbinv_range */
150 cpufunc_nullop, /* l2cache_wbinv_all */
151 (void *)cpufunc_nullop, /* l2cache_wbinv_range */
152 (void *)cpufunc_nullop, /* l2cache_inv_range */
153 (void *)cpufunc_nullop, /* l2cache_wb_range */
154
155 /* Other functions */
156
157 cpufunc_nullop, /* flush_prefetchbuf */
158 cpufunc_nullop, /* drain_writebuf */
159 cpufunc_nullop, /* flush_brnchtgt_C */
160 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
161
162 (void *)cpufunc_nullop, /* sleep */
163
164 /* Soft functions */
165
166 late_abort_fixup, /* dataabt_fixup */
167 cpufunc_null_fixup, /* prefetchabt_fixup */
168
169 arm7tdmi_context_switch, /* context_switch */
170
171 arm7tdmi_setup /* cpu setup */
172
173 };
174 #endif /* CPU_ARM7TDMI */
175
176 #ifdef CPU_ARM8
177 struct cpu_functions arm8_cpufuncs = {
178 /* CPU functions */
179
180 cpufunc_id, /* id */
181 cpufunc_nullop, /* cpwait */
182
183 /* MMU functions */
184
185 cpufunc_control, /* control */
186 cpufunc_domains, /* domain */
187 arm8_setttb, /* setttb */
188 cpufunc_faultstatus, /* faultstatus */
189 cpufunc_faultaddress, /* faultaddress */
190
191 /* TLB functions */
192
193 arm8_tlb_flushID, /* tlb_flushID */
194 arm8_tlb_flushID_SE, /* tlb_flushID_SE */
195 arm8_tlb_flushID, /* tlb_flushI */
196 arm8_tlb_flushID_SE, /* tlb_flushI_SE */
197 arm8_tlb_flushID, /* tlb_flushD */
198 arm8_tlb_flushID_SE, /* tlb_flushD_SE */
199
200 /* Cache operations */
201
202 cpufunc_nullop, /* icache_sync_all */
203 (void *)cpufunc_nullop, /* icache_sync_range */
204
205 arm8_cache_purgeID, /* dcache_wbinv_all */
206 (void *)arm8_cache_purgeID, /* dcache_wbinv_range */
207 /*XXX*/ (void *)arm8_cache_purgeID, /* dcache_inv_range */
208 (void *)arm8_cache_cleanID, /* dcache_wb_range */
209
210 arm8_cache_purgeID, /* idcache_wbinv_all */
211 (void *)arm8_cache_purgeID, /* idcache_wbinv_range */
212 cpufunc_nullop, /* l2cache_wbinv_all */
213 (void *)cpufunc_nullop, /* l2cache_wbinv_range */
214 (void *)cpufunc_nullop, /* l2cache_inv_range */
215 (void *)cpufunc_nullop, /* l2cache_wb_range */
216
217 /* Other functions */
218
219 cpufunc_nullop, /* flush_prefetchbuf */
220 cpufunc_nullop, /* drain_writebuf */
221 cpufunc_nullop, /* flush_brnchtgt_C */
222 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
223
224 (void *)cpufunc_nullop, /* sleep */
225
226 /* Soft functions */
227
228 cpufunc_null_fixup, /* dataabt_fixup */
229 cpufunc_null_fixup, /* prefetchabt_fixup */
230
231 arm8_context_switch, /* context_switch */
232
233 arm8_setup /* cpu setup */
234 };
235 #endif /* CPU_ARM8 */
236
237 #ifdef CPU_ARM9
238 struct cpu_functions arm9_cpufuncs = {
239 /* CPU functions */
240
241 cpufunc_id, /* id */
242 cpufunc_nullop, /* cpwait */
243
244 /* MMU functions */
245
246 cpufunc_control, /* control */
247 cpufunc_domains, /* Domain */
248 arm9_setttb, /* Setttb */
249 cpufunc_faultstatus, /* Faultstatus */
250 cpufunc_faultaddress, /* Faultaddress */
251
252 /* TLB functions */
253
254 armv4_tlb_flushID, /* tlb_flushID */
255 arm9_tlb_flushID_SE, /* tlb_flushID_SE */
256 armv4_tlb_flushI, /* tlb_flushI */
257 (void *)armv4_tlb_flushI, /* tlb_flushI_SE */
258 armv4_tlb_flushD, /* tlb_flushD */
259 armv4_tlb_flushD_SE, /* tlb_flushD_SE */
260
261 /* Cache operations */
262
263 arm9_icache_sync_all, /* icache_sync_all */
264 arm9_icache_sync_range, /* icache_sync_range */
265
266 arm9_dcache_wbinv_all, /* dcache_wbinv_all */
267 arm9_dcache_wbinv_range, /* dcache_wbinv_range */
268 /*XXX*/ arm9_dcache_wbinv_range, /* dcache_inv_range */
269 arm9_dcache_wb_range, /* dcache_wb_range */
270
271 arm9_idcache_wbinv_all, /* idcache_wbinv_all */
272 arm9_idcache_wbinv_range, /* idcache_wbinv_range */
273 cpufunc_nullop, /* l2cache_wbinv_all */
274 (void *)cpufunc_nullop, /* l2cache_wbinv_range */
275 (void *)cpufunc_nullop, /* l2cache_inv_range */
276 (void *)cpufunc_nullop, /* l2cache_wb_range */
277
278 /* Other functions */
279
280 cpufunc_nullop, /* flush_prefetchbuf */
281 armv4_drain_writebuf, /* drain_writebuf */
282 cpufunc_nullop, /* flush_brnchtgt_C */
283 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
284
285 (void *)cpufunc_nullop, /* sleep */
286
287 /* Soft functions */
288
289 cpufunc_null_fixup, /* dataabt_fixup */
290 cpufunc_null_fixup, /* prefetchabt_fixup */
291
292 arm9_context_switch, /* context_switch */
293
294 arm9_setup /* cpu setup */
295
296 };
297 #endif /* CPU_ARM9 */
298
299 #if defined(CPU_ARM9E) || defined(CPU_ARM10)
300 struct cpu_functions armv5_ec_cpufuncs = {
301 /* CPU functions */
302
303 cpufunc_id, /* id */
304 cpufunc_nullop, /* cpwait */
305
306 /* MMU functions */
307
308 cpufunc_control, /* control */
309 cpufunc_domains, /* Domain */
310 armv5_ec_setttb, /* Setttb */
311 cpufunc_faultstatus, /* Faultstatus */
312 cpufunc_faultaddress, /* Faultaddress */
313
314 /* TLB functions */
315
316 armv4_tlb_flushID, /* tlb_flushID */
317 arm10_tlb_flushID_SE, /* tlb_flushID_SE */
318 armv4_tlb_flushI, /* tlb_flushI */
319 arm10_tlb_flushI_SE, /* tlb_flushI_SE */
320 armv4_tlb_flushD, /* tlb_flushD */
321 armv4_tlb_flushD_SE, /* tlb_flushD_SE */
322
323 /* Cache operations */
324
325 armv5_ec_icache_sync_all, /* icache_sync_all */
326 armv5_ec_icache_sync_range, /* icache_sync_range */
327
328 armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */
329 armv5_ec_dcache_wbinv_range, /* dcache_wbinv_range */
330 /*XXX*/ armv5_ec_dcache_wbinv_range, /* dcache_inv_range */
331 armv5_ec_dcache_wb_range, /* dcache_wb_range */
332
333 armv5_ec_idcache_wbinv_all, /* idcache_wbinv_all */
334 armv5_ec_idcache_wbinv_range, /* idcache_wbinv_range */
335
336 cpufunc_nullop, /* l2cache_wbinv_all */
337 (void *)cpufunc_nullop, /* l2cache_wbinv_range */
338 (void *)cpufunc_nullop, /* l2cache_inv_range */
339 (void *)cpufunc_nullop, /* l2cache_wb_range */
340
341 /* Other functions */
342
343 cpufunc_nullop, /* flush_prefetchbuf */
344 armv4_drain_writebuf, /* drain_writebuf */
345 cpufunc_nullop, /* flush_brnchtgt_C */
346 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
347
348 (void *)cpufunc_nullop, /* sleep */
349
350 /* Soft functions */
351
352 cpufunc_null_fixup, /* dataabt_fixup */
353 cpufunc_null_fixup, /* prefetchabt_fixup */
354
355 arm10_context_switch, /* context_switch */
356
357 arm10_setup /* cpu setup */
358
359 };
360
361 struct cpu_functions feroceon_cpufuncs = {
362 /* CPU functions */
363
364 cpufunc_id, /* id */
365 cpufunc_nullop, /* cpwait */
366
367 /* MMU functions */
368
369 cpufunc_control, /* control */
370 cpufunc_domains, /* Domain */
371 feroceon_setttb, /* Setttb */
372 cpufunc_faultstatus, /* Faultstatus */
373 cpufunc_faultaddress, /* Faultaddress */
374
375 /* TLB functions */
376
377 armv4_tlb_flushID, /* tlb_flushID */
378 arm10_tlb_flushID_SE, /* tlb_flushID_SE */
379 armv4_tlb_flushI, /* tlb_flushI */
380 arm10_tlb_flushI_SE, /* tlb_flushI_SE */
381 armv4_tlb_flushD, /* tlb_flushD */
382 armv4_tlb_flushD_SE, /* tlb_flushD_SE */
383
384 /* Cache operations */
385
386 armv5_ec_icache_sync_all, /* icache_sync_all */
387 armv5_ec_icache_sync_range, /* icache_sync_range */
388
389 armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */
390 feroceon_dcache_wbinv_range, /* dcache_wbinv_range */
391 feroceon_dcache_inv_range, /* dcache_inv_range */
392 feroceon_dcache_wb_range, /* dcache_wb_range */
393
394 armv5_ec_idcache_wbinv_all, /* idcache_wbinv_all */
395 feroceon_idcache_wbinv_range, /* idcache_wbinv_all */
396
397 feroceon_l2cache_wbinv_all, /* l2cache_wbinv_all */
398 feroceon_l2cache_wbinv_range, /* l2cache_wbinv_range */
399 feroceon_l2cache_inv_range, /* l2cache_inv_range */
400 feroceon_l2cache_wb_range, /* l2cache_wb_range */
401
402 /* Other functions */
403
404 cpufunc_nullop, /* flush_prefetchbuf */
405 armv4_drain_writebuf, /* drain_writebuf */
406 cpufunc_nullop, /* flush_brnchtgt_C */
407 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
408
409 (void *)cpufunc_nullop, /* sleep */
410
411 /* Soft functions */
412
413 cpufunc_null_fixup, /* dataabt_fixup */
414 cpufunc_null_fixup, /* prefetchabt_fixup */
415
416 arm10_context_switch, /* context_switch */
417
418 arm10_setup /* cpu setup */
419 };
420 #endif /* CPU_ARM9E || CPU_ARM10 */
421
422 #ifdef CPU_ARM10
423 struct cpu_functions arm10_cpufuncs = {
424 /* CPU functions */
425
426 cpufunc_id, /* id */
427 cpufunc_nullop, /* cpwait */
428
429 /* MMU functions */
430
431 cpufunc_control, /* control */
432 cpufunc_domains, /* Domain */
433 arm10_setttb, /* Setttb */
434 cpufunc_faultstatus, /* Faultstatus */
435 cpufunc_faultaddress, /* Faultaddress */
436
437 /* TLB functions */
438
439 armv4_tlb_flushID, /* tlb_flushID */
440 arm10_tlb_flushID_SE, /* tlb_flushID_SE */
441 armv4_tlb_flushI, /* tlb_flushI */
442 arm10_tlb_flushI_SE, /* tlb_flushI_SE */
443 armv4_tlb_flushD, /* tlb_flushD */
444 armv4_tlb_flushD_SE, /* tlb_flushD_SE */
445
446 /* Cache operations */
447
448 arm10_icache_sync_all, /* icache_sync_all */
449 arm10_icache_sync_range, /* icache_sync_range */
450
451 arm10_dcache_wbinv_all, /* dcache_wbinv_all */
452 arm10_dcache_wbinv_range, /* dcache_wbinv_range */
453 arm10_dcache_inv_range, /* dcache_inv_range */
454 arm10_dcache_wb_range, /* dcache_wb_range */
455
456 arm10_idcache_wbinv_all, /* idcache_wbinv_all */
457 arm10_idcache_wbinv_range, /* idcache_wbinv_range */
458 cpufunc_nullop, /* l2cache_wbinv_all */
459 (void *)cpufunc_nullop, /* l2cache_wbinv_range */
460 (void *)cpufunc_nullop, /* l2cache_inv_range */
461 (void *)cpufunc_nullop, /* l2cache_wb_range */
462
463 /* Other functions */
464
465 cpufunc_nullop, /* flush_prefetchbuf */
466 armv4_drain_writebuf, /* drain_writebuf */
467 cpufunc_nullop, /* flush_brnchtgt_C */
468 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
469
470 (void *)cpufunc_nullop, /* sleep */
471
472 /* Soft functions */
473
474 cpufunc_null_fixup, /* dataabt_fixup */
475 cpufunc_null_fixup, /* prefetchabt_fixup */
476
477 arm10_context_switch, /* context_switch */
478
479 arm10_setup /* cpu setup */
480
481 };
482 #endif /* CPU_ARM10 */
483
484 #ifdef CPU_SA110
485 struct cpu_functions sa110_cpufuncs = {
486 /* CPU functions */
487
488 cpufunc_id, /* id */
489 cpufunc_nullop, /* cpwait */
490
491 /* MMU functions */
492
493 cpufunc_control, /* control */
494 cpufunc_domains, /* domain */
495 sa1_setttb, /* setttb */
496 cpufunc_faultstatus, /* faultstatus */
497 cpufunc_faultaddress, /* faultaddress */
498
499 /* TLB functions */
500
501 armv4_tlb_flushID, /* tlb_flushID */
502 sa1_tlb_flushID_SE, /* tlb_flushID_SE */
503 armv4_tlb_flushI, /* tlb_flushI */
504 (void *)armv4_tlb_flushI, /* tlb_flushI_SE */
505 armv4_tlb_flushD, /* tlb_flushD */
506 armv4_tlb_flushD_SE, /* tlb_flushD_SE */
507
508 /* Cache operations */
509
510 sa1_cache_syncI, /* icache_sync_all */
511 sa1_cache_syncI_rng, /* icache_sync_range */
512
513 sa1_cache_purgeD, /* dcache_wbinv_all */
514 sa1_cache_purgeD_rng, /* dcache_wbinv_range */
515 /*XXX*/ sa1_cache_purgeD_rng, /* dcache_inv_range */
516 sa1_cache_cleanD_rng, /* dcache_wb_range */
517
518 sa1_cache_purgeID, /* idcache_wbinv_all */
519 sa1_cache_purgeID_rng, /* idcache_wbinv_range */
520 cpufunc_nullop, /* l2cache_wbinv_all */
521 (void *)cpufunc_nullop, /* l2cache_wbinv_range */
522 (void *)cpufunc_nullop, /* l2cache_inv_range */
523 (void *)cpufunc_nullop, /* l2cache_wb_range */
524
525 /* Other functions */
526
527 cpufunc_nullop, /* flush_prefetchbuf */
528 armv4_drain_writebuf, /* drain_writebuf */
529 cpufunc_nullop, /* flush_brnchtgt_C */
530 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
531
532 (void *)cpufunc_nullop, /* sleep */
533
534 /* Soft functions */
535
536 cpufunc_null_fixup, /* dataabt_fixup */
537 cpufunc_null_fixup, /* prefetchabt_fixup */
538
539 sa110_context_switch, /* context_switch */
540
541 sa110_setup /* cpu setup */
542 };
543 #endif /* CPU_SA110 */
544
545 #if defined(CPU_SA1100) || defined(CPU_SA1110)
546 struct cpu_functions sa11x0_cpufuncs = {
547 /* CPU functions */
548
549 cpufunc_id, /* id */
550 cpufunc_nullop, /* cpwait */
551
552 /* MMU functions */
553
554 cpufunc_control, /* control */
555 cpufunc_domains, /* domain */
556 sa1_setttb, /* setttb */
557 cpufunc_faultstatus, /* faultstatus */
558 cpufunc_faultaddress, /* faultaddress */
559
560 /* TLB functions */
561
562 armv4_tlb_flushID, /* tlb_flushID */
563 sa1_tlb_flushID_SE, /* tlb_flushID_SE */
564 armv4_tlb_flushI, /* tlb_flushI */
565 (void *)armv4_tlb_flushI, /* tlb_flushI_SE */
566 armv4_tlb_flushD, /* tlb_flushD */
567 armv4_tlb_flushD_SE, /* tlb_flushD_SE */
568
569 /* Cache operations */
570
571 sa1_cache_syncI, /* icache_sync_all */
572 sa1_cache_syncI_rng, /* icache_sync_range */
573
574 sa1_cache_purgeD, /* dcache_wbinv_all */
575 sa1_cache_purgeD_rng, /* dcache_wbinv_range */
576 /*XXX*/ sa1_cache_purgeD_rng, /* dcache_inv_range */
577 sa1_cache_cleanD_rng, /* dcache_wb_range */
578
579 sa1_cache_purgeID, /* idcache_wbinv_all */
580 sa1_cache_purgeID_rng, /* idcache_wbinv_range */
581 cpufunc_nullop, /* l2cache_wbinv_all */
582 (void *)cpufunc_nullop, /* l2cache_wbinv_range */
583 (void *)cpufunc_nullop, /* l2cache_inv_range */
584 (void *)cpufunc_nullop, /* l2cache_wb_range */
585
586 /* Other functions */
587
588 sa11x0_drain_readbuf, /* flush_prefetchbuf */
589 armv4_drain_writebuf, /* drain_writebuf */
590 cpufunc_nullop, /* flush_brnchtgt_C */
591 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
592
593 sa11x0_cpu_sleep, /* sleep */
594
595 /* Soft functions */
596
597 cpufunc_null_fixup, /* dataabt_fixup */
598 cpufunc_null_fixup, /* prefetchabt_fixup */
599
600 sa11x0_context_switch, /* context_switch */
601
602 sa11x0_setup /* cpu setup */
603 };
604 #endif /* CPU_SA1100 || CPU_SA1110 */
605
606 #ifdef CPU_IXP12X0
607 struct cpu_functions ixp12x0_cpufuncs = {
608 /* CPU functions */
609
610 cpufunc_id, /* id */
611 cpufunc_nullop, /* cpwait */
612
613 /* MMU functions */
614
615 cpufunc_control, /* control */
616 cpufunc_domains, /* domain */
617 sa1_setttb, /* setttb */
618 cpufunc_faultstatus, /* faultstatus */
619 cpufunc_faultaddress, /* faultaddress */
620
621 /* TLB functions */
622
623 armv4_tlb_flushID, /* tlb_flushID */
624 sa1_tlb_flushID_SE, /* tlb_flushID_SE */
625 armv4_tlb_flushI, /* tlb_flushI */
626 (void *)armv4_tlb_flushI, /* tlb_flushI_SE */
627 armv4_tlb_flushD, /* tlb_flushD */
628 armv4_tlb_flushD_SE, /* tlb_flushD_SE */
629
630 /* Cache operations */
631
632 sa1_cache_syncI, /* icache_sync_all */
633 sa1_cache_syncI_rng, /* icache_sync_range */
634
635 sa1_cache_purgeD, /* dcache_wbinv_all */
636 sa1_cache_purgeD_rng, /* dcache_wbinv_range */
637 /*XXX*/ sa1_cache_purgeD_rng, /* dcache_inv_range */
638 sa1_cache_cleanD_rng, /* dcache_wb_range */
639
640 sa1_cache_purgeID, /* idcache_wbinv_all */
641 sa1_cache_purgeID_rng, /* idcache_wbinv_range */
642 cpufunc_nullop, /* l2cache_wbinv_all */
643 (void *)cpufunc_nullop, /* l2cache_wbinv_range */
644 (void *)cpufunc_nullop, /* l2cache_inv_range */
645 (void *)cpufunc_nullop, /* l2cache_wb_range */
646
647 /* Other functions */
648
649 ixp12x0_drain_readbuf, /* flush_prefetchbuf */
650 armv4_drain_writebuf, /* drain_writebuf */
651 cpufunc_nullop, /* flush_brnchtgt_C */
652 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
653
654 (void *)cpufunc_nullop, /* sleep */
655
656 /* Soft functions */
657
658 cpufunc_null_fixup, /* dataabt_fixup */
659 cpufunc_null_fixup, /* prefetchabt_fixup */
660
661 ixp12x0_context_switch, /* context_switch */
662
663 ixp12x0_setup /* cpu setup */
664 };
665 #endif /* CPU_IXP12X0 */
666
667 #if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
668 defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
669 defined(CPU_XSCALE_80219)
670
671 struct cpu_functions xscale_cpufuncs = {
672 /* CPU functions */
673
674 cpufunc_id, /* id */
675 xscale_cpwait, /* cpwait */
676
677 /* MMU functions */
678
679 xscale_control, /* control */
680 cpufunc_domains, /* domain */
681 xscale_setttb, /* setttb */
682 cpufunc_faultstatus, /* faultstatus */
683 cpufunc_faultaddress, /* faultaddress */
684
685 /* TLB functions */
686
687 armv4_tlb_flushID, /* tlb_flushID */
688 xscale_tlb_flushID_SE, /* tlb_flushID_SE */
689 armv4_tlb_flushI, /* tlb_flushI */
690 (void *)armv4_tlb_flushI, /* tlb_flushI_SE */
691 armv4_tlb_flushD, /* tlb_flushD */
692 armv4_tlb_flushD_SE, /* tlb_flushD_SE */
693
694 /* Cache operations */
695
696 xscale_cache_syncI, /* icache_sync_all */
697 xscale_cache_syncI_rng, /* icache_sync_range */
698
699 xscale_cache_purgeD, /* dcache_wbinv_all */
700 xscale_cache_purgeD_rng, /* dcache_wbinv_range */
701 xscale_cache_flushD_rng, /* dcache_inv_range */
702 xscale_cache_cleanD_rng, /* dcache_wb_range */
703
704 xscale_cache_purgeID, /* idcache_wbinv_all */
705 xscale_cache_purgeID_rng, /* idcache_wbinv_range */
706 cpufunc_nullop, /* l2cache_wbinv_all */
707 (void *)cpufunc_nullop, /* l2cache_wbinv_range */
708 (void *)cpufunc_nullop, /* l2cache_inv_range */
709 (void *)cpufunc_nullop, /* l2cache_wb_range */
710
711 /* Other functions */
712
713 cpufunc_nullop, /* flush_prefetchbuf */
714 armv4_drain_writebuf, /* drain_writebuf */
715 cpufunc_nullop, /* flush_brnchtgt_C */
716 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
717
718 xscale_cpu_sleep, /* sleep */
719
720 /* Soft functions */
721
722 cpufunc_null_fixup, /* dataabt_fixup */
723 cpufunc_null_fixup, /* prefetchabt_fixup */
724
725 xscale_context_switch, /* context_switch */
726
727 xscale_setup /* cpu setup */
728 };
729 #endif
730 /* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425
731 CPU_XSCALE_80219 */
732
733 #ifdef CPU_XSCALE_81342
734 struct cpu_functions xscalec3_cpufuncs = {
735 /* CPU functions */
736
737 cpufunc_id, /* id */
738 xscale_cpwait, /* cpwait */
739
740 /* MMU functions */
741
742 xscale_control, /* control */
743 cpufunc_domains, /* domain */
744 xscalec3_setttb, /* setttb */
745 cpufunc_faultstatus, /* faultstatus */
746 cpufunc_faultaddress, /* faultaddress */
747
748 /* TLB functions */
749
750 armv4_tlb_flushID, /* tlb_flushID */
751 xscale_tlb_flushID_SE, /* tlb_flushID_SE */
752 armv4_tlb_flushI, /* tlb_flushI */
753 (void *)armv4_tlb_flushI, /* tlb_flushI_SE */
754 armv4_tlb_flushD, /* tlb_flushD */
755 armv4_tlb_flushD_SE, /* tlb_flushD_SE */
756
757 /* Cache operations */
758
759 xscalec3_cache_syncI, /* icache_sync_all */
760 xscalec3_cache_syncI_rng, /* icache_sync_range */
761
762 xscalec3_cache_purgeD, /* dcache_wbinv_all */
763 xscalec3_cache_purgeD_rng, /* dcache_wbinv_range */
764 xscale_cache_flushD_rng, /* dcache_inv_range */
765 xscalec3_cache_cleanD_rng, /* dcache_wb_range */
766
767 xscalec3_cache_purgeID, /* idcache_wbinv_all */
768 xscalec3_cache_purgeID_rng, /* idcache_wbinv_range */
769 xscalec3_l2cache_purge, /* l2cache_wbinv_all */
770 xscalec3_l2cache_purge_rng, /* l2cache_wbinv_range */
771 xscalec3_l2cache_flush_rng, /* l2cache_inv_range */
772 xscalec3_l2cache_clean_rng, /* l2cache_wb_range */
773
774 /* Other functions */
775
776 cpufunc_nullop, /* flush_prefetchbuf */
777 armv4_drain_writebuf, /* drain_writebuf */
778 cpufunc_nullop, /* flush_brnchtgt_C */
779 (void *)cpufunc_nullop, /* flush_brnchtgt_E */
780
781 xscale_cpu_sleep, /* sleep */
782
783 /* Soft functions */
784
785 cpufunc_null_fixup, /* dataabt_fixup */
786 cpufunc_null_fixup, /* prefetchabt_fixup */
787
788 xscalec3_context_switch, /* context_switch */
789
790 xscale_setup /* cpu setup */
791 };
792 #endif /* CPU_XSCALE_81342 */
793 /*
794 * Global constants also used by locore.s
795 */
796
797 struct cpu_functions cpufuncs;
798 u_int cputype;
799 u_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore.s */
800
801 #if defined(CPU_ARM7TDMI) || defined(CPU_ARM8) || defined(CPU_ARM9) || \
802 defined (CPU_ARM9E) || defined (CPU_ARM10) || \
803 defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
804 defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
805 defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)
806
807 static void get_cachetype_cp15(void);
808
809 /* Additional cache information local to this file. Log2 of some of the
810 above numbers. */
811 static int arm_dcache_l2_nsets;
812 static int arm_dcache_l2_assoc;
813 static int arm_dcache_l2_linesize;
814
815 static void
816 get_cachetype_cp15()
817 {
818 u_int ctype, isize, dsize;
819 u_int multiplier;
820
821 __asm __volatile("mrc p15, 0, %0, c0, c0, 1"
822 : "=r" (ctype));
823
824 /*
825 * ...and thus spake the ARM ARM:
826 *
827 * If an <opcode2> value corresponding to an unimplemented or
828 * reserved ID register is encountered, the System Control
829 * processor returns the value of the main ID register.
830 */
831 if (ctype == cpufunc_id())
832 goto out;
833
834 if ((ctype & CPU_CT_S) == 0)
835 arm_pcache_unified = 1;
836
837 /*
838 * If you want to know how this code works, go read the ARM ARM.
839 */
840
841 arm_pcache_type = CPU_CT_CTYPE(ctype);
842
843 if (arm_pcache_unified == 0) {
844 isize = CPU_CT_ISIZE(ctype);
845 multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2;
846 arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3);
847 if (CPU_CT_xSIZE_ASSOC(isize) == 0) {
848 if (isize & CPU_CT_xSIZE_M)
849 arm_picache_line_size = 0; /* not present */
850 else
851 arm_picache_ways = 1;
852 } else {
853 arm_picache_ways = multiplier <<
854 (CPU_CT_xSIZE_ASSOC(isize) - 1);
855 }
856 arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
857 }
858
859 dsize = CPU_CT_DSIZE(ctype);
860 multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
861 arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
862 if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
863 if (dsize & CPU_CT_xSIZE_M)
864 arm_pdcache_line_size = 0; /* not present */
865 else
866 arm_pdcache_ways = 1;
867 } else {
868 arm_pdcache_ways = multiplier <<
869 (CPU_CT_xSIZE_ASSOC(dsize) - 1);
870 }
871 arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
872
873 arm_dcache_align = arm_pdcache_line_size;
874
875 arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2;
876 arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3;
877 arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) -
878 CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize);
879
880 out:
881 arm_dcache_align_mask = arm_dcache_align - 1;
882 }
883 #endif /* ARM7TDMI || ARM8 || ARM9 || XSCALE */
884
885 #if defined(CPU_SA110) || defined(CPU_SA1100) || defined(CPU_SA1110) || \
886 defined(CPU_IXP12X0)
887 /* Cache information for CPUs without cache type registers. */
888 struct cachetab {
889 u_int32_t ct_cpuid;
890 int ct_pcache_type;
891 int ct_pcache_unified;
892 int ct_pdcache_size;
893 int ct_pdcache_line_size;
894 int ct_pdcache_ways;
895 int ct_picache_size;
896 int ct_picache_line_size;
897 int ct_picache_ways;
898 };
899
900 struct cachetab cachetab[] = {
901 /* cpuid, cache type, u, dsiz, ls, wy, isiz, ls, wy */
902 /* XXX is this type right for SA-1? */
903 { CPU_ID_SA110, CPU_CT_CTYPE_WB1, 0, 16384, 32, 32, 16384, 32, 32 },
904 { CPU_ID_SA1100, CPU_CT_CTYPE_WB1, 0, 8192, 32, 32, 16384, 32, 32 },
905 { CPU_ID_SA1110, CPU_CT_CTYPE_WB1, 0, 8192, 32, 32, 16384, 32, 32 },
906 { CPU_ID_IXP1200, CPU_CT_CTYPE_WB1, 0, 16384, 32, 32, 16384, 32, 32 }, /* XXX */
907 { 0, 0, 0, 0, 0, 0, 0, 0}
908 };
909
910 static void get_cachetype_table(void);
911
912 static void
913 get_cachetype_table()
914 {
915 int i;
916 u_int32_t cpuid = cpufunc_id();
917
918 for (i = 0; cachetab[i].ct_cpuid != 0; i++) {
919 if (cachetab[i].ct_cpuid == (cpuid & CPU_ID_CPU_MASK)) {
920 arm_pcache_type = cachetab[i].ct_pcache_type;
921 arm_pcache_unified = cachetab[i].ct_pcache_unified;
922 arm_pdcache_size = cachetab[i].ct_pdcache_size;
923 arm_pdcache_line_size =
924 cachetab[i].ct_pdcache_line_size;
925 arm_pdcache_ways = cachetab[i].ct_pdcache_ways;
926 arm_picache_size = cachetab[i].ct_picache_size;
927 arm_picache_line_size =
928 cachetab[i].ct_picache_line_size;
929 arm_picache_ways = cachetab[i].ct_picache_ways;
930 }
931 }
932 arm_dcache_align = arm_pdcache_line_size;
933
934 arm_dcache_align_mask = arm_dcache_align - 1;
935 }
936
937 #endif /* SA110 || SA1100 || SA1111 || IXP12X0 */
938
939 /*
940 * Cannot panic here as we may not have a console yet ...
941 */
942
943 int
944 set_cpufuncs()
945 {
946 cputype = cpufunc_id();
947 cputype &= CPU_ID_CPU_MASK;
948
949 /*
950 * NOTE: cpu_do_powersave defaults to off. If we encounter a
951 * CPU type where we want to use it by default, then we set it.
952 */
953
954 #ifdef CPU_ARM7TDMI
955 if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD &&
956 CPU_ID_IS7(cputype) &&
957 (cputype & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V4T) {
958 cpufuncs = arm7tdmi_cpufuncs;
959 cpu_reset_needs_v4_MMU_disable = 0;
960 get_cachetype_cp15();
961 pmap_pte_init_generic();
962 goto out;
963 }
964 #endif
965 #ifdef CPU_ARM8
966 if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD &&
967 (cputype & 0x0000f000) == 0x00008000) {
968 cpufuncs = arm8_cpufuncs;
969 cpu_reset_needs_v4_MMU_disable = 0; /* XXX correct? */
970 get_cachetype_cp15();
971 pmap_pte_init_arm8();
972 goto out;
973 }
974 #endif /* CPU_ARM8 */
975 #ifdef CPU_ARM9
976 if (((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD ||
977 (cputype & CPU_ID_ |