initial commit
[freebsd-arm:freebsd-arm.git] / 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$");
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 /* PRIMARY CACHE VARIABLES */
87 int     arm_picache_size;
88 int     arm_picache_line_size;
89 int     arm_picache_ways;
90
91 int     arm_pdcache_size;       /* and unified */
92 int     arm_pdcache_line_size;
93 int     arm_pdcache_ways;
94
95 int     arm_pcache_type;
96 int     arm_pcache_unified;
97
98 int     arm_dcache_align;
99 int     arm_dcache_align_mask;
100
101 /* 1 == use cpu_sleep(), 0 == don't */
102 int cpu_do_powersave;
103 int ctrl;
104
105 #ifdef CPU_ARM7TDMI
106 struct cpu_functions arm7tdmi_cpufuncs = {
107         /* CPU functions */
108         
109         cpufunc_id,                     /* id                   */
110         cpufunc_nullop,                 /* cpwait               */
111
112         /* MMU functions */
113
114         cpufunc_control,                /* control              */
115         cpufunc_domains,                /* domain               */
116         arm7tdmi_setttb,                /* setttb               */
117         cpufunc_faultstatus,            /* faultstatus          */
118         cpufunc_faultaddress,           /* faultaddress         */
119
120         /* TLB functions */
121
122         arm7tdmi_tlb_flushID,           /* tlb_flushID          */
123         arm7tdmi_tlb_flushID_SE,        /* tlb_flushID_SE       */
124         arm7tdmi_tlb_flushID,           /* tlb_flushI           */
125         arm7tdmi_tlb_flushID_SE,        /* tlb_flushI_SE        */
126         arm7tdmi_tlb_flushID,           /* tlb_flushD           */
127         arm7tdmi_tlb_flushID_SE,        /* tlb_flushD_SE        */
128
129         /* Cache operations */
130
131         cpufunc_nullop,                 /* icache_sync_all      */
132         (void *)cpufunc_nullop,         /* icache_sync_range    */
133
134         arm7tdmi_cache_flushID,         /* dcache_wbinv_all     */
135         (void *)arm7tdmi_cache_flushID, /* dcache_wbinv_range   */
136         (void *)arm7tdmi_cache_flushID, /* dcache_inv_range     */
137         (void *)cpufunc_nullop,         /* dcache_wb_range      */
138
139         arm7tdmi_cache_flushID,         /* idcache_wbinv_all    */
140         (void *)arm7tdmi_cache_flushID, /* 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
146         /* Other functions */
147
148         cpufunc_nullop,                 /* flush_prefetchbuf    */
149         cpufunc_nullop,                 /* drain_writebuf       */
150         cpufunc_nullop,                 /* flush_brnchtgt_C     */
151         (void *)cpufunc_nullop,         /* flush_brnchtgt_E     */
152
153         (void *)cpufunc_nullop,         /* sleep                */
154
155         /* Soft functions */
156
157         late_abort_fixup,               /* dataabt_fixup        */
158         cpufunc_null_fixup,             /* prefetchabt_fixup    */
159
160         arm7tdmi_context_switch,        /* context_switch       */
161
162         arm7tdmi_setup                  /* cpu setup            */
163
164 };
165 #endif  /* CPU_ARM7TDMI */
166
167 #ifdef CPU_ARM8
168 struct cpu_functions arm8_cpufuncs = {
169         /* CPU functions */
170         
171         cpufunc_id,                     /* id                   */
172         cpufunc_nullop,                 /* cpwait               */
173
174         /* MMU functions */
175
176         cpufunc_control,                /* control              */
177         cpufunc_domains,                /* domain               */
178         arm8_setttb,                    /* setttb               */
179         cpufunc_faultstatus,            /* faultstatus          */
180         cpufunc_faultaddress,           /* faultaddress         */
181
182         /* TLB functions */
183
184         arm8_tlb_flushID,               /* tlb_flushID          */
185         arm8_tlb_flushID_SE,            /* tlb_flushID_SE       */
186         arm8_tlb_flushID,               /* tlb_flushI           */
187         arm8_tlb_flushID_SE,            /* tlb_flushI_SE        */
188         arm8_tlb_flushID,               /* tlb_flushD           */
189         arm8_tlb_flushID_SE,            /* tlb_flushD_SE        */
190
191         /* Cache operations */
192
193         cpufunc_nullop,                 /* icache_sync_all      */
194         (void *)cpufunc_nullop,         /* icache_sync_range    */
195
196         arm8_cache_purgeID,             /* dcache_wbinv_all     */
197         (void *)arm8_cache_purgeID,     /* dcache_wbinv_range   */
198 /*XXX*/ (void *)arm8_cache_purgeID,     /* dcache_inv_range     */
199         (void *)arm8_cache_cleanID,     /* dcache_wb_range      */
200
201         arm8_cache_purgeID,             /* idcache_wbinv_all    */
202         (void *)arm8_cache_purgeID,     /* idcache_wbinv_range  */
203         cpufunc_nullop,                 /* l2cache_wbinv_all    */
204         (void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
205         (void *)cpufunc_nullop,         /* l2cache_inv_range    */
206         (void *)cpufunc_nullop,         /* l2cache_wb_range     */
207
208         /* Other functions */
209
210         cpufunc_nullop,                 /* flush_prefetchbuf    */
211         cpufunc_nullop,                 /* drain_writebuf       */
212         cpufunc_nullop,                 /* flush_brnchtgt_C     */
213         (void *)cpufunc_nullop,         /* flush_brnchtgt_E     */
214
215         (void *)cpufunc_nullop,         /* sleep                */
216
217         /* Soft functions */
218
219         cpufunc_null_fixup,             /* dataabt_fixup        */
220         cpufunc_null_fixup,             /* prefetchabt_fixup    */
221
222         arm8_context_switch,            /* context_switch       */
223
224         arm8_setup                      /* cpu setup            */
225 };          
226 #endif  /* CPU_ARM8 */
227
228 #ifdef CPU_ARM9
229 struct cpu_functions arm9_cpufuncs = {
230         /* CPU functions */
231
232         cpufunc_id,                     /* id                   */
233         cpufunc_nullop,                 /* cpwait               */
234
235         /* MMU functions */
236
237         cpufunc_control,                /* control              */
238         cpufunc_domains,                /* Domain               */
239         arm9_setttb,                    /* Setttb               */
240         cpufunc_faultstatus,            /* Faultstatus          */
241         cpufunc_faultaddress,           /* Faultaddress         */
242
243         /* TLB functions */
244
245         armv4_tlb_flushID,              /* tlb_flushID          */
246         arm9_tlb_flushID_SE,            /* tlb_flushID_SE       */
247         armv4_tlb_flushI,               /* tlb_flushI           */
248         (void *)armv4_tlb_flushI,       /* tlb_flushI_SE        */
249         armv4_tlb_flushD,               /* tlb_flushD           */
250         armv4_tlb_flushD_SE,            /* tlb_flushD_SE        */
251
252         /* Cache operations */
253
254         arm9_icache_sync_all,           /* icache_sync_all      */
255         arm9_icache_sync_range,         /* icache_sync_range    */
256
257         arm9_dcache_wbinv_all,          /* dcache_wbinv_all     */
258         arm9_dcache_wbinv_range,        /* dcache_wbinv_range   */
259         arm9_dcache_inv_range,          /* dcache_inv_range     */
260         arm9_dcache_wb_range,           /* dcache_wb_range      */
261
262         arm9_idcache_wbinv_all,         /* idcache_wbinv_all    */
263         arm9_idcache_wbinv_range,       /* idcache_wbinv_range  */
264         cpufunc_nullop,                 /* l2cache_wbinv_all    */
265         (void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
266         (void *)cpufunc_nullop,         /* l2cache_inv_range    */
267         (void *)cpufunc_nullop,         /* l2cache_wb_range     */
268
269         /* Other functions */
270
271         cpufunc_nullop,                 /* flush_prefetchbuf    */
272         armv4_drain_writebuf,           /* drain_writebuf       */
273         cpufunc_nullop,                 /* flush_brnchtgt_C     */
274         (void *)cpufunc_nullop,         /* flush_brnchtgt_E     */
275
276         (void *)cpufunc_nullop,         /* sleep                */
277
278         /* Soft functions */
279
280         cpufunc_null_fixup,             /* dataabt_fixup        */
281         cpufunc_null_fixup,             /* prefetchabt_fixup    */
282
283         arm9_context_switch,            /* context_switch       */
284
285         arm9_setup                      /* cpu setup            */
286
287 };
288 #endif /* CPU_ARM9 */
289
290 #if defined(CPU_ARM9E) || defined(CPU_ARM10)
291 struct cpu_functions armv5_ec_cpufuncs = {
292         /* CPU functions */
293
294         cpufunc_id,                     /* id                   */
295         cpufunc_nullop,                 /* cpwait               */
296
297         /* MMU functions */
298
299         cpufunc_control,                /* control              */
300         cpufunc_domains,                /* Domain               */
301         armv5_ec_setttb,                /* Setttb               */
302         cpufunc_faultstatus,            /* Faultstatus          */
303         cpufunc_faultaddress,           /* Faultaddress         */
304
305         /* TLB functions */
306
307         armv4_tlb_flushID,              /* tlb_flushID          */
308         arm10_tlb_flushID_SE,           /* tlb_flushID_SE       */
309         armv4_tlb_flushI,               /* tlb_flushI           */
310         arm10_tlb_flushI_SE,            /* tlb_flushI_SE        */
311         armv4_tlb_flushD,               /* tlb_flushD           */
312         armv4_tlb_flushD_SE,            /* tlb_flushD_SE        */
313
314         /* Cache operations */
315
316         armv5_ec_icache_sync_all,       /* icache_sync_all      */
317         armv5_ec_icache_sync_range,     /* icache_sync_range    */
318
319         armv5_ec_dcache_wbinv_all,      /* dcache_wbinv_all     */
320         armv5_ec_dcache_wbinv_range,    /* dcache_wbinv_range   */
321         armv5_ec_dcache_inv_range,      /* dcache_inv_range     */
322         armv5_ec_dcache_wb_range,       /* dcache_wb_range      */
323
324         armv5_ec_idcache_wbinv_all,     /* idcache_wbinv_all    */
325         armv5_ec_idcache_wbinv_range,   /* idcache_wbinv_range  */
326
327         cpufunc_nullop,                 /* l2cache_wbinv_all    */
328         (void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
329         (void *)cpufunc_nullop,         /* l2cache_inv_range    */
330         (void *)cpufunc_nullop,         /* l2cache_wb_range     */
331                                  
332         /* Other functions */
333
334         cpufunc_nullop,                 /* flush_prefetchbuf    */
335         armv4_drain_writebuf,           /* drain_writebuf       */
336         cpufunc_nullop,                 /* flush_brnchtgt_C     */
337         (void *)cpufunc_nullop,         /* flush_brnchtgt_E     */
338
339         (void *)cpufunc_nullop,         /* sleep                */
340
341         /* Soft functions */
342
343         cpufunc_null_fixup,             /* dataabt_fixup        */
344         cpufunc_null_fixup,             /* prefetchabt_fixup    */
345
346         arm10_context_switch,           /* context_switch       */
347
348         arm10_setup                     /* cpu setup            */
349
350 };
351
352 struct cpu_functions sheeva_cpufuncs = {
353         /* CPU functions */
354
355         cpufunc_id,                     /* id                   */
356         cpufunc_nullop,                 /* cpwait               */
357
358         /* MMU functions */
359
360         cpufunc_control,                /* control              */
361         cpufunc_domains,                /* Domain               */
362         sheeva_setttb,                  /* Setttb               */
363         cpufunc_faultstatus,            /* Faultstatus          */
364         cpufunc_faultaddress,           /* Faultaddress         */
365
366         /* TLB functions */
367
368         armv4_tlb_flushID,              /* tlb_flushID          */
369         arm10_tlb_flushID_SE,           /* tlb_flushID_SE       */
370         armv4_tlb_flushI,               /* tlb_flushI           */
371         arm10_tlb_flushI_SE,            /* tlb_flushI_SE        */
372         armv4_tlb_flushD,               /* tlb_flushD           */
373         armv4_tlb_flushD_SE,            /* tlb_flushD_SE        */
374
375         /* Cache operations */
376
377         armv5_ec_icache_sync_all,       /* icache_sync_all      */
378         armv5_ec_icache_sync_range,     /* icache_sync_range    */
379
380         armv5_ec_dcache_wbinv_all,      /* dcache_wbinv_all     */
381         sheeva_dcache_wbinv_range,      /* dcache_wbinv_range   */
382         sheeva_dcache_inv_range,        /* dcache_inv_range     */
383         sheeva_dcache_wb_range,         /* dcache_wb_range      */
384
385         armv5_ec_idcache_wbinv_all,     /* idcache_wbinv_all    */
386         sheeva_idcache_wbinv_range,     /* idcache_wbinv_all    */
387
388         sheeva_l2cache_wbinv_all,       /* l2cache_wbinv_all    */
389         sheeva_l2cache_wbinv_range,     /* l2cache_wbinv_range  */
390         sheeva_l2cache_inv_range,       /* l2cache_inv_range    */
391         sheeva_l2cache_wb_range,        /* l2cache_wb_range     */
392
393         /* Other functions */
394
395         cpufunc_nullop,                 /* flush_prefetchbuf    */
396         armv4_drain_writebuf,           /* drain_writebuf       */
397         cpufunc_nullop,                 /* flush_brnchtgt_C     */
398         (void *)cpufunc_nullop,         /* flush_brnchtgt_E     */
399
400         (void *)cpufunc_nullop,         /* sleep                */
401
402         /* Soft functions */
403
404         cpufunc_null_fixup,             /* dataabt_fixup        */
405         cpufunc_null_fixup,             /* prefetchabt_fixup    */
406
407         arm10_context_switch,           /* context_switch       */
408
409         arm10_setup                     /* cpu setup            */
410 };
411 #endif /* CPU_ARM9E || CPU_ARM10 */
412
413 #ifdef CPU_ARM10
414 struct cpu_functions arm10_cpufuncs = {
415         /* CPU functions */
416
417         cpufunc_id,                     /* id                   */
418         cpufunc_nullop,                 /* cpwait               */
419
420         /* MMU functions */
421
422         cpufunc_control,                /* control              */
423         cpufunc_domains,                /* Domain               */
424         arm10_setttb,                   /* Setttb               */
425         cpufunc_faultstatus,            /* Faultstatus          */
426         cpufunc_faultaddress,           /* Faultaddress         */
427
428         /* TLB functions */
429
430         armv4_tlb_flushID,              /* tlb_flushID          */
431         arm10_tlb_flushID_SE,           /* tlb_flushID_SE       */
432         armv4_tlb_flushI,               /* tlb_flushI           */
433         arm10_tlb_flushI_SE,            /* tlb_flushI_SE        */
434         armv4_tlb_flushD,               /* tlb_flushD           */
435         armv4_tlb_flushD_SE,            /* tlb_flushD_SE        */
436
437         /* Cache operations */
438
439         arm10_icache_sync_all,          /* icache_sync_all      */
440         arm10_icache_sync_range,        /* icache_sync_range    */
441
442         arm10_dcache_wbinv_all,         /* dcache_wbinv_all     */
443         arm10_dcache_wbinv_range,       /* dcache_wbinv_range   */
444         arm10_dcache_inv_range,         /* dcache_inv_range     */
445         arm10_dcache_wb_range,          /* dcache_wb_range      */
446
447         arm10_idcache_wbinv_all,        /* idcache_wbinv_all    */
448         arm10_idcache_wbinv_range,      /* idcache_wbinv_range  */
449         cpufunc_nullop,                 /* l2cache_wbinv_all    */
450         (void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
451         (void *)cpufunc_nullop,         /* l2cache_inv_range    */
452         (void *)cpufunc_nullop,         /* l2cache_wb_range     */
453
454         /* Other functions */
455
456         cpufunc_nullop,                 /* flush_prefetchbuf    */
457         armv4_drain_writebuf,           /* drain_writebuf       */
458         cpufunc_nullop,                 /* flush_brnchtgt_C     */
459         (void *)cpufunc_nullop,         /* flush_brnchtgt_E     */
460
461         (void *)cpufunc_nullop,         /* sleep                */
462
463         /* Soft functions */
464
465         cpufunc_null_fixup,             /* dataabt_fixup        */
466         cpufunc_null_fixup,             /* prefetchabt_fixup    */
467
468         arm10_context_switch,           /* context_switch       */
469
470         arm10_setup                     /* cpu setup            */
471
472 };
473 #endif /* CPU_ARM10 */
474
475 #ifdef CPU_SA110
476 struct cpu_functions sa110_cpufuncs = {
477         /* CPU functions */
478         
479         cpufunc_id,                     /* id                   */
480         cpufunc_nullop,                 /* cpwait               */
481
482         /* MMU functions */
483
484         cpufunc_control,                /* control              */
485         cpufunc_domains,                /* domain               */
486         sa1_setttb,                     /* setttb               */
487         cpufunc_faultstatus,            /* faultstatus          */
488         cpufunc_faultaddress,           /* faultaddress         */
489
490         /* TLB functions */
491
492         armv4_tlb_flushID,              /* tlb_flushID          */
493         sa1_tlb_flushID_SE,             /* tlb_flushID_SE       */
494         armv4_tlb_flushI,               /* tlb_flushI           */
495         (void *)armv4_tlb_flushI,       /* tlb_flushI_SE        */
496         armv4_tlb_flushD,               /* tlb_flushD           */
497         armv4_tlb_flushD_SE,            /* tlb_flushD_SE        */
498
499         /* Cache operations */
500
501         sa1_cache_syncI,                /* icache_sync_all      */
502         sa1_cache_syncI_rng,            /* icache_sync_range    */
503
504         sa1_cache_purgeD,               /* dcache_wbinv_all     */
505         sa1_cache_purgeD_rng,           /* dcache_wbinv_range   */
506 /*XXX*/ sa1_cache_purgeD_rng,           /* dcache_inv_range     */
507         sa1_cache_cleanD_rng,           /* dcache_wb_range      */
508
509         sa1_cache_purgeID,              /* idcache_wbinv_all    */
510         sa1_cache_purgeID_rng,          /* idcache_wbinv_range  */
511         cpufunc_nullop,                 /* l2cache_wbinv_all    */
512         (void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
513         (void *)cpufunc_nullop,         /* l2cache_inv_range    */
514         (void *)cpufunc_nullop,         /* l2cache_wb_range     */
515
516         /* Other functions */
517
518         cpufunc_nullop,                 /* flush_prefetchbuf    */
519         armv4_drain_writebuf,           /* drain_writebuf       */
520         cpufunc_nullop,                 /* flush_brnchtgt_C     */
521         (void *)cpufunc_nullop,         /* flush_brnchtgt_E     */
522
523         (void *)cpufunc_nullop,         /* sleep                */
524
525         /* Soft functions */
526
527         cpufunc_null_fixup,             /* dataabt_fixup        */
528         cpufunc_null_fixup,             /* prefetchabt_fixup    */
529
530         sa110_context_switch,           /* context_switch       */
531
532         sa110_setup                     /* cpu setup            */
533 };          
534 #endif  /* CPU_SA110 */
535
536 #if defined(CPU_SA1100) || defined(CPU_SA1110)
537 struct cpu_functions sa11x0_cpufuncs = {
538         /* CPU functions */
539         
540         cpufunc_id,                     /* id                   */
541         cpufunc_nullop,                 /* cpwait               */
542
543         /* MMU functions */
544
545         cpufunc_control,                /* control              */
546         cpufunc_domains,                /* domain               */
547         sa1_setttb,                     /* setttb               */
548         cpufunc_faultstatus,            /* faultstatus          */
549         cpufunc_faultaddress,           /* faultaddress         */
550
551         /* TLB functions */
552
553         armv4_tlb_flushID,              /* tlb_flushID          */
554         sa1_tlb_flushID_SE,             /* tlb_flushID_SE       */
555         armv4_tlb_flushI,               /* tlb_flushI           */
556         (void *)armv4_tlb_flushI,       /* tlb_flushI_SE        */
557         armv4_tlb_flushD,               /* tlb_flushD           */
558         armv4_tlb_flushD_SE,            /* tlb_flushD_SE        */
559
560         /* Cache operations */
561
562         sa1_cache_syncI,                /* icache_sync_all      */
563         sa1_cache_syncI_rng,            /* icache_sync_range    */
564
565         sa1_cache_purgeD,               /* dcache_wbinv_all     */
566         sa1_cache_purgeD_rng,           /* dcache_wbinv_range   */
567 /*XXX*/ sa1_cache_purgeD_rng,           /* dcache_inv_range     */
568         sa1_cache_cleanD_rng,           /* dcache_wb_range      */
569
570         sa1_cache_purgeID,              /* idcache_wbinv_all    */
571         sa1_cache_purgeID_rng,          /* idcache_wbinv_range  */
572         cpufunc_nullop,                 /* l2cache_wbinv_all    */
573         (void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
574         (void *)cpufunc_nullop,         /* l2cache_inv_range    */
575         (void *)cpufunc_nullop,         /* l2cache_wb_range     */
576
577         /* Other functions */
578
579         sa11x0_drain_readbuf,           /* flush_prefetchbuf    */
580         armv4_drain_writebuf,           /* drain_writebuf       */
581         cpufunc_nullop,                 /* flush_brnchtgt_C     */
582         (void *)cpufunc_nullop,         /* flush_brnchtgt_E     */
583
584         sa11x0_cpu_sleep,               /* sleep                */
585
586         /* Soft functions */
587
588         cpufunc_null_fixup,             /* dataabt_fixup        */
589         cpufunc_null_fixup,             /* prefetchabt_fixup    */
590
591         sa11x0_context_switch,          /* context_switch       */
592
593         sa11x0_setup                    /* cpu setup            */
594 };          
595 #endif  /* CPU_SA1100 || CPU_SA1110 */
596
597 #ifdef CPU_IXP12X0
598 struct cpu_functions ixp12x0_cpufuncs = {
599         /* CPU functions */
600         
601         cpufunc_id,                     /* id                   */
602         cpufunc_nullop,                 /* cpwait               */
603
604         /* MMU functions */
605
606         cpufunc_control,                /* control              */
607         cpufunc_domains,                /* domain               */
608         sa1_setttb,                     /* setttb               */
609         cpufunc_faultstatus,            /* faultstatus          */
610         cpufunc_faultaddress,           /* faultaddress         */
611
612         /* TLB functions */
613
614         armv4_tlb_flushID,              /* tlb_flushID          */
615         sa1_tlb_flushID_SE,             /* tlb_flushID_SE       */
616         armv4_tlb_flushI,               /* tlb_flushI           */
617         (void *)armv4_tlb_flushI,       /* tlb_flushI_SE        */
618         armv4_tlb_flushD,               /* tlb_flushD           */
619         armv4_tlb_flushD_SE,            /* tlb_flushD_SE        */
620
621         /* Cache operations */
622
623         sa1_cache_syncI,                /* icache_sync_all      */
624         sa1_cache_syncI_rng,            /* icache_sync_range    */
625
626         sa1_cache_purgeD,               /* dcache_wbinv_all     */
627         sa1_cache_purgeD_rng,           /* dcache_wbinv_range   */
628 /*XXX*/ sa1_cache_purgeD_rng,           /* dcache_inv_range     */
629         sa1_cache_cleanD_rng,           /* dcache_wb_range      */
630
631         sa1_cache_purgeID,              /* idcache_wbinv_all    */
632         sa1_cache_purgeID_rng,          /* idcache_wbinv_range  */
633         cpufunc_nullop,                 /* l2cache_wbinv_all    */
634         (void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
635         (void *)cpufunc_nullop,         /* l2cache_inv_range    */
636         (void *)cpufunc_nullop,         /* l2cache_wb_range     */
637
638         /* Other functions */
639
640         ixp12x0_drain_readbuf,                  /* flush_prefetchbuf    */
641         armv4_drain_writebuf,           /* drain_writebuf       */
642         cpufunc_nullop,                 /* flush_brnchtgt_C     */
643         (void *)cpufunc_nullop,         /* flush_brnchtgt_E     */
644
645         (void *)cpufunc_nullop,         /* sleep                */
646
647         /* Soft functions */
648
649         cpufunc_null_fixup,             /* dataabt_fixup        */
650         cpufunc_null_fixup,             /* prefetchabt_fixup    */
651
652         ixp12x0_context_switch,         /* context_switch       */
653
654         ixp12x0_setup                   /* cpu setup            */
655 };          
656 #endif  /* CPU_IXP12X0 */
657
658 #if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
659   defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
660   defined(CPU_XSCALE_80219)
661
662 struct cpu_functions xscale_cpufuncs = {
663         /* CPU functions */
664         
665         cpufunc_id,                     /* id                   */
666         xscale_cpwait,                  /* cpwait               */
667
668         /* MMU functions */
669
670         xscale_control,                 /* control              */
671         cpufunc_domains,                /* domain               */
672         xscale_setttb,                  /* setttb               */
673         cpufunc_faultstatus,            /* faultstatus          */
674         cpufunc_faultaddress,           /* faultaddress         */
675
676         /* TLB functions */
677
678         armv4_tlb_flushID,              /* tlb_flushID          */
679         xscale_tlb_flushID_SE,          /* tlb_flushID_SE       */
680         armv4_tlb_flushI,               /* tlb_flushI           */
681         (void *)armv4_tlb_flushI,       /* tlb_flushI_SE        */
682         armv4_tlb_flushD,               /* tlb_flushD           */
683         armv4_tlb_flushD_SE,            /* tlb_flushD_SE        */
684
685         /* Cache operations */
686
687         xscale_cache_syncI,             /* icache_sync_all      */
688         xscale_cache_syncI_rng,         /* icache_sync_range    */
689
690         xscale_cache_purgeD,            /* dcache_wbinv_all     */
691         xscale_cache_purgeD_rng,        /* dcache_wbinv_range   */
692         xscale_cache_flushD_rng,        /* dcache_inv_range     */
693         xscale_cache_cleanD_rng,        /* dcache_wb_range      */
694
695         xscale_cache_purgeID,           /* idcache_wbinv_all    */
696         xscale_cache_purgeID_rng,       /* idcache_wbinv_range  */
697         cpufunc_nullop,                 /* l2cache_wbinv_all    */
698         (void *)cpufunc_nullop,         /* l2cache_wbinv_range  */
699         (void *)cpufunc_nullop,         /* l2cache_inv_range    */
700         (void *)cpufunc_nullop,         /* l2cache_wb_range     */
701
702         /* Other functions */
703
704         cpufunc_nullop,                 /* flush_prefetchbuf    */
705         armv4_drain_writebuf,           /* drain_writebuf       */
706         cpufunc_nullop,                 /* flush_brnchtgt_C     */
707         (void *)cpufunc_nullop,         /* flush_brnchtgt_E     */
708
709         xscale_cpu_sleep,               /* sleep                */
710
711         /* Soft functions */
712
713         cpufunc_null_fixup,             /* dataabt_fixup        */
714         cpufunc_null_fixup,             /* prefetchabt_fixup    */
715
716         xscale_context_switch,          /* context_switch       */
717
718         xscale_setup                    /* cpu setup            */
719 };
720 #endif
721 /* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425
722    CPU_XSCALE_80219 */
723
724 #ifdef CPU_XSCALE_81342
725 struct cpu_functions xscalec3_cpufuncs = {
726         /* CPU functions */
727         
728         cpufunc_id,                     /* id                   */
729         xscale_cpwait,                  /* cpwait               */
730
731         /* MMU functions */
732
733         xscale_control,                 /* control              */
734         cpufunc_domains,                /* domain               */
735         xscalec3_setttb,                /* setttb               */
736         cpufunc_faultstatus,            /* faultstatus          */
737         cpufunc_faultaddress,           /* faultaddress         */
738
739         /* TLB functions */
740
741         armv4_tlb_flushID,              /* tlb_flushID          */
742         xscale_tlb_flushID_SE,          /* tlb_flushID_SE       */
743         armv4_tlb_flushI,               /* tlb_flushI           */
744         (void *)armv4_tlb_flushI,       /* tlb_flushI_SE        */
745         armv4_tlb_flushD,               /* tlb_flushD           */
746         armv4_tlb_flushD_SE,            /* tlb_flushD_SE        */
747
748         /* Cache operations */
749
750         xscalec3_cache_syncI,           /* icache_sync_all      */
751         xscalec3_cache_syncI_rng,       /* icache_sync_range    */
752
753         xscalec3_cache_purgeD,          /* dcache_wbinv_all     */
754         xscalec3_cache_purgeD_rng,      /* dcache_wbinv_range   */
755         xscale_cache_flushD_rng,        /* dcache_inv_range     */
756         xscalec3_cache_cleanD_rng,      /* dcache_wb_range      */
757
758         xscalec3_cache_purgeID,         /* idcache_wbinv_all    */
759         xscalec3_cache_purgeID_rng,     /* idcache_wbinv_range  */
760         xscalec3_l2cache_purge,         /* l2cache_wbinv_all    */
761         xscalec3_l2cache_purge_rng,     /* l2cache_wbinv_range  */
762         xscalec3_l2cache_flush_rng,     /* l2cache_inv_range    */
763         xscalec3_l2cache_clean_rng,     /* l2cache_wb_range     */
764
765         /* Other functions */
766
767         cpufunc_nullop,                 /* flush_prefetchbuf    */
768         armv4_drain_writebuf,           /* drain_writebuf       */
769         cpufunc_nullop,                 /* flush_brnchtgt_C     */
770         (void *)cpufunc_nullop,         /* flush_brnchtgt_E     */
771
772         xscale_cpu_sleep,               /* sleep                */
773
774         /* Soft functions */
775
776         cpufunc_null_fixup,             /* dataabt_fixup        */
777         cpufunc_null_fixup,             /* prefetchabt_fixup    */
778
779         xscalec3_context_switch,        /* context_switch       */
780
781         xscale_setup                    /* cpu setup            */
782 };
783 #endif /* CPU_XSCALE_81342 */
784
785
786 #if defined(CPU_FA526)
787 struct cpu_functions fa526_cpufuncs = {
788         /* CPU functions */
789
790         .cf_id                  = cpufunc_id,
791         .cf_cpwait              = cpufunc_nullop,
792
793         /* MMU functions */
794
795         .cf_control             = cpufunc_control,
796         .cf_domains             = cpufunc_domains,
797         .cf_setttb              = fa526_setttb,
798         .cf_faultstatus         = cpufunc_faultstatus,
799         .cf_faultaddress        = cpufunc_faultaddress,
800
801         /* TLB functions */
802
803         .cf_tlb_flushID         = armv4_tlb_flushID,
804         .cf_tlb_flushID_SE      = fa526_tlb_flushID_SE,
805         .cf_tlb_flushI          = armv4_tlb_flushI,
806         .cf_tlb_flushI_SE       = fa526_tlb_flushI_SE,
807         .cf_tlb_flushD          = armv4_tlb_flushD,
808         .cf_tlb_flushD_SE       = armv4_tlb_flushD_SE,
809
810         /* Cache operations */
811
812         .cf_icache_sync_all     = fa526_icache_sync_all,
813         .cf_icache_sync_range   = fa526_icache_sync_range,
814
815         .cf_dcache_wbinv_all    = fa526_dcache_wbinv_all,
816         .cf_dcache_wbinv_range  = fa526_dcache_wbinv_range,
817         .cf_dcache_inv_range    = fa526_dcache_inv_range,
818         .cf_dcache_wb_range     = fa526_dcache_wb_range,
819
820         .cf_idcache_wbinv_all   = fa526_idcache_wbinv_all,
821         .cf_idcache_wbinv_range = fa526_idcache_wbinv_range,
822
823
824         .cf_l2cache_wbinv_all = cpufunc_nullop,
825         .cf_l2cache_wbinv_range = (void *)cpufunc_nullop,
826         .cf_l2cache_inv_range = (void *)cpufunc_nullop,
827         .cf_l2cache_wb_range = (void *)cpufunc_nullop,
828
829
830         /* Other functions */
831
832         .cf_flush_prefetchbuf   = fa526_flush_prefetchbuf,
833         .cf_drain_writebuf      = armv4_drain_writebuf,
834         .cf_flush_brnchtgt_C    = cpufunc_nullop,
835         .cf_flush_brnchtgt_E    = fa526_flush_brnchtgt_E,
836
837         .cf_sleep               = fa526_cpu_sleep,
838
839         /* Soft functions */
840
841         .cf_dataabt_fixup       = cpufunc_null_fixup,
842         .cf_prefetchabt_fixup   = cpufunc_null_fixup,
843
844         .cf_context_switch      = fa526_context_switch,
845
846         .cf_setup               = fa526_setup
847 };
848 #endif  /* CPU_FA526 */
849
850
851 /*
852  * Global constants also used by locore.s
853  */
854
855 struct cpu_functions cpufuncs;
856 u_int cputype;
857 u_int cpu_reset_needs_v4_MMU_disable;   /* flag used in locore.s */
858
859 #if defined(CPU_ARM7TDMI) || defined(CPU_ARM8) || defined(CPU_ARM9) || \
860   defined (CPU_ARM9E) || defined (CPU_ARM10) ||                        \
861   defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) ||            \
862   defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) ||          \
863   defined(CPU_FA526) ||                                        \
864   defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)
865
866 static void get_cachetype_cp15(void);
867
868 /* Additional cache information local to this file.  Log2 of some of the
869    above numbers.  */
870 static int      arm_dcache_l2_nsets;
871 static int      arm_dcache_l2_assoc;
872 static int      arm_dcache_l2_linesize;
873
874 static void
875 get_cachetype_cp15()
876 {
877         u_int ctype, isize, dsize;
878         u_int multiplier;
879
880         __asm __volatile("mrc p15, 0, %0, c0, c0, 1"
881                 : "=r" (ctype));
882
883         /*
884          * ...and thus spake the ARM ARM:
885          *
886          * If an <opcode2> value corresponding to an unimplemented or
887          * reserved ID register is encountered, the System Control
888          * processor returns the value of the main ID register.
889          */
890         if (ctype == cpufunc_id())
891                 goto out;
892
893         if ((ctype & CPU_CT_S) == 0)
894                 arm_pcache_unified = 1;
895
896         /*
897          * If you want to know how this code works, go read the ARM ARM.
898          */
899
900         arm_pcache_type = CPU_CT_CTYPE(ctype);
901
902         if (arm_pcache_unified == 0) {
903                 isize = CPU_CT_ISIZE(ctype);
904                 multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2;
905                 arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3);
906                 if (CPU_CT_xSIZE_ASSOC(isize) == 0) {
907                         if (isize & CPU_CT_xSIZE_M)
908                                 arm_picache_line_size = 0; /* not present */
909                         else
910                                 arm_picache_ways = 1;
911                 } else {
912                         arm_picache_ways = multiplier <<
913                             (CPU_CT_xSIZE_ASSOC(isize) - 1);
914                 }
915                 arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
916         }
917
918         dsize = CPU_CT_DSIZE(ctype);
919         multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
920         arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
921         if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
922                 if (dsize & CPU_CT_xSIZE_M)
923                         arm_pdcache_line_size = 0; /* not present */
924                 else
925                         arm_pdcache_ways = 1;
926         } else {
927                 arm_pdcache_ways = multiplier <<
928                     (CPU_CT_xSIZE_ASSOC(dsize) - 1);
929         }
930         arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
931
932         arm_dcache_align = arm_pdcache_line_size;
933
934         arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2;
935         arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3;
936         arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) -
937             CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize);
938
939  out:
940         arm_dcache_align_mask = arm_dcache_align - 1;
941 }
942 #endif /* ARM7TDMI || ARM8 || ARM9 || XSCALE */
943
944 #if defined(CPU_SA110) || defined(CPU_SA1100) || defined(CPU_SA1110) || \
945     defined(CPU_IXP12X0)
946 /* Cache information for CPUs without cache type registers. */
947 struct cachetab {
948         u_int32_t ct_cpuid;
949         int     ct_pcache_type;
950         int     ct_pcache_unified;
951         int     ct_pdcache_size;
952         int     ct_pdcache_line_size;
953         int     ct_pdcache_ways;
954         int     ct_picache_size;
955         int     ct_picache_line_size;
956         int     ct_picache_ways;
957 };
958
959 struct cachetab cachetab[] = {
960     /* cpuid,           cache type,       u,  dsiz, ls, wy,  isiz, ls, wy */
961     /* XXX is this type right for SA-1? */
962     { CPU_ID_SA110,     CPU_CT_CTYPE_WB1, 0, 16384, 32, 32, 16384, 32, 32 },
963     { CPU_ID_SA1100,    CPU_CT_CTYPE_WB1, 0,  8192, 32, 32, 16384, 32, 32 },
964     { CPU_ID_SA1110,    CPU_CT_CTYPE_WB1, 0,  8192, 32, 32, 16384, 32, 32 },
965     { CPU_ID_IXP1200,   CPU_CT_CTYPE_WB1, 0, 16384, 32, 32, 16384, 32, 32 }, /* XXX */
966     { 0, 0, 0, 0, 0, 0, 0, 0}
967 };
968
969 static void get_cachetype_table(void);
970
971 static void
972 get_cachetype_table()
973 {
974         int i;
975         u_int32_t cpuid = cpufunc_id();
976
977         for (i = 0; cachetab[i].ct_cpuid != 0; i++) {
978                 if (cachetab[i].ct_cpuid == (cpuid & CPU_ID_CPU_MASK)) {
979                         arm_pcache_type = cachetab[i].ct_pcache_type;
980                         arm_pcache_unified = cachetab[i].ct_pcache_unified;
981                         arm_pdcache_size = cachetab[i].ct_pdcache_size;
982                         arm_pdcache_line_size =
983                             cachetab[i].ct_pdcache_line_size;
984                         arm_pdcache_ways = cachetab[i].ct_pdcache_ways;
985                         arm_picache_size = cachetab[i].ct_picache_size;
986                         arm_picache_line_size =
987                             cachetab[i].ct_picache_line_size;
988                         arm_picache_ways = cachetab[i].ct_picache_ways;
989                 }
990         }
991         arm_dcache_align = arm_pdcache_line_size;
992
993         arm_dcache_align_mask = arm_dcache_align - 1;
994 }
995
996 #endif /* SA110 || SA1100 || SA1111 || IXP12X0 */
997
998 /*
999  * Cannot panic here as we may not have a console yet ...
1000  */
1001
1002 int
1003 set_cpufuncs()
1004 {
1005         cputype = cpufunc_id();
1006         cputype &= CPU_ID_CPU_MASK;
1007
1008         /*
1009          * NOTE: cpu_do_powersave defaults to off.  If we encounter a
1010          * CPU type where we want to use it by default, then we set it.
1011          */
1012
1013 #ifdef CPU_ARM7TDMI
1014         if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD &&
1015             CPU_ID_IS7(cputype) &&
1016             (cputype & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V4T) {
1017                 cpufuncs = arm7tdmi_cpufuncs;
1018                 cpu_reset_needs_v4_MMU_disable = 0;
1019                 get_cachetype_cp15();
1020                 pmap_pte_init_generic();
1021                 goto out;
1022         }
1023 #endif  
1024 #ifdef CPU_ARM8
1025         if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD &&
1026             (cputype & 0x0000f000) == 0x00008000) {
1027                 cpufuncs = arm8_cpufuncs;
1028                 cpu_reset_needs_v4_MMU_disable = 0;     /* XXX correct? */
1029                 get_cachetype_cp15();
1030                 pmap_pte_init_arm8();
1031                 goto out;
1032         }
1033 #endif  /* CPU_ARM8 */
1034 #ifdef CPU_ARM9
1035         if (((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD ||
1036              (cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_TI) &&
1037             (cputype & 0x0000f000) == 0x00009000) {
1038                 cpufuncs = arm9_cpufuncs;
1039                 cpu_reset_needs_v4_MMU_disable = 1;     /* V4 or higher */
1040                 get_cachetype_cp15();
1041                 arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize;
1042                 arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize +
1043                     arm_dcache_l2_nsets)) - arm9_dcache_sets_inc;
1044                 arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc);
1045                 arm9_dcache_index_max = 0U - arm9_dcache_index_inc;
1046 #ifdef ARM9_CACHE_WRITE_THROUGH
1047                 pmap_pte_init_arm9();
1048 #else
1049                 pmap_pte_init_generic();
1050 #endif
1051                 goto out;
1052         }
1053 #endif /* CPU_ARM9 */
1054 #if defined(CPU_ARM9E) || defined(CPU_ARM10)
1055         if (cputype == CPU_ID_ARM926EJS || cputype == CPU_ID_ARM1026EJS ||
1056             cputype == CPU_ID_MV88FR131 || cputype == CPU_ID_MV88FR571_VD ||
1057             cputype == CPU_ID_MV88FR571_41) {
1058                 if (cputype == CPU_ID_MV88FR131 ||
1059                     cputype == CPU_ID_MV88FR571_VD ||
1060                     cputype == CPU_ID_MV88FR571_41) {
1061
1062                         cpufuncs = sheeva_cpufuncs;
1063                         /*
1064                          * Workaround for Marvell MV78100 CPU: Cache prefetch
1065                          * mechanism may affect the cache coherency validity,
1066                          * so it needs to be disabled.
1067                          *
1068                          * Refer to errata document MV-S501058-00C.pdf (p. 3.1
1069                          * L2 Prefetching Mechanism) for details.
1070                          */
1071                         if (cputype == CPU_ID_MV88FR571_VD ||
1072                             cputype == CPU_ID_MV88FR571_41) {
1073                                 sheeva_control_ext(0xffffffff,
1074                                     FC_DCACHE_STREAM_EN | FC_WR_ALLOC_EN |
1075                                     FC_BRANCH_TARG_BUF_DIS | FC_L2CACHE_EN |
1076                                     FC_L2_PREF_DIS);
1077                         } else {
1078                                 sheeva_control_ext(0xffffffff,
1079                                     FC_DCACHE_STREAM_EN | FC_WR_ALLOC_EN |
1080                                     FC_BRANCH_TARG_BUF_DIS | FC_L2CACHE_EN);
1081                         }
1082                 } else
1083                         cpufuncs = armv5_ec_cpufuncs;
1084
1085                 cpu_reset_needs_v4_MMU_disable = 1;     /* V4 or higher */
1086                 get_cachetype_cp15();
1087                 pmap_pte_init_generic();
1088                 goto out;
1089         }
1090 #endif /* CPU_ARM9E || CPU_ARM10 */
1091 #ifdef CPU_ARM10
1092         if (/* cputype == CPU_ID_ARM1020T || */
1093             cputype == CPU_ID_ARM1020E) {
1094                 /*
1095                  * Select write-through cacheing (this isn't really an
1096                  * option on ARM1020T).
1097                  */
1098                 cpufuncs = arm10_cpufuncs;
1099                 cpu_reset_needs_v4_MMU_disable = 1;     /* V4 or higher */
1100                 get_cachetype_cp15();
1101                 arm10_dcache_sets_inc = 1U << arm_dcache_l2_linesize;
1102                 arm10_dcache_sets_max = 
1103                     (1U << (arm_dcache_l2_linesize + arm_dcache_l2_nsets)) -
1104                     arm10_dcache_sets_inc;
1105                 arm10_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc);
1106                 arm10_dcache_index_max = 0U - arm10_dcache_index_inc;
1107                 pmap_pte_init_generic();
1108                 goto out;
1109         }
1110 #endif /* CPU_ARM10 */
1111 #ifdef CPU_SA110
1112         if (cputype == CPU_ID_SA110) {
1113                 cpufuncs = sa110_cpufuncs;
1114                 cpu_reset_needs_v4_MMU_disable = 1;     /* SA needs it */
1115                 get_cachetype_table();
1116                 pmap_pte_init_sa1();
1117                 goto out;
1118         }
1119 #endif  /* CPU_SA110 */
1120 #ifdef CPU_SA1100
1121         if (cputype == CPU_ID_SA1100) {
1122                 cpufuncs = sa11x0_cpufuncs;
1123                 cpu_reset_needs_v4_MMU_disable = 1;     /* SA needs it  */
1124                 get_cachetype_table();
1125                 pmap_pte_init_sa1();
1126                 /* Use powersave on this CPU. */
1127                 cpu_do_powersave = 1;
1128
1129                 goto out;
1130         }
1131 #endif  /* CPU_SA1100 */
1132 #ifdef CPU_SA1110
1133         if (cputype == CPU_ID_SA1110) {
1134                 cpufuncs = sa11x0_cpufuncs;
1135                 cpu_reset_needs_v4_MMU_disable = 1;     /* SA needs it  */
1136                 get_cachetype_table();
1137                 pmap_pte_init_sa1();
1138                 /* Use powersave on this CPU. */
1139                 cpu_do_powersave = 1;
1140
1141                 goto out;
1142         }
1143 #endif  /* CPU_SA1110 */
1144 #ifdef CPU_FA526
1145         if (cputype == CPU_ID_FA526) {
1146                 cpufuncs = fa526_cpufuncs;
1147                 cpu_reset_needs_v4_MMU_disable = 1;     /* SA needs it  */
1148                 get_cachetype_cp15();
1149                 pmap_pte_init_generic();
1150
1151                 /* Use powersave on this CPU. */
1152                 cpu_do_powersave = 1;
1153
1154                 goto out;
1155         }
1156 #endif  /* CPU_FA526 */
1157 #ifdef CPU_IXP12X0
1158         if (cputype == CPU_ID_IXP1200) {
1159                 cpufuncs = ixp12x0_cpufuncs;
1160                 cpu_reset_needs_v4_MMU_disable = 1;
1161                 get_cachetype_table();
1162                 pmap_pte_init_sa1();
1163                 goto out;
1164         }
1165 #endif  /* CPU_IXP12X0 */
1166 #ifdef CPU_XSCALE_80200
1167         if (cputype == CPU_ID_80200) {
1168                 int rev = cpufunc_id() & CPU_ID_REVISION_MASK;
1169
1170                 i80200_icu_init();
1171
1172 #if defined(XSCALE_CCLKCFG)
1173                 /*
1174                  * Crank CCLKCFG to maximum legal value.
1175                  */
1176                 __asm __volatile ("mcr p14, 0, %0, c6, c0, 0"
1177                         :
1178                         : "r" (XSCALE_CCLKCFG));
1179 #endif
1180
1181                 /*
1182                  * XXX Disable ECC in the Bus Controller Unit; we
1183                  * don't really support it, yet.  Clear any pending
1184                  * error indications.
1185                  */
1186                 __asm __volatile("mcr p13, 0, %0, c0, c1, 0"
1187                         :
1188                         : "r" (BCUCTL_E0|BCUCTL_E1|BCUCTL_EV));
1189
1190                 cpufuncs = xscale_cpufuncs;
1191                 /*
1192                  * i80200 errata: Step-A0 and A1 have a bug where
1193                  * D$ dirty bits are not cleared on "invalidate by
1194                  * address".
1195                  *
1196                  * Workaround: Clean cache line before invalidating.
1197                  */
1198                 if (rev == 0 || rev == 1)
1199                         cpufuncs.cf_dcache_inv_range = xscale_cache_purgeD_rng;
1200
1201                 cpu_reset_needs_v4_MMU_disable = 1;     /* XScale needs it */
1202                 get_cachetype_cp15();
1203                 pmap_pte_init_xscale();
1204                 goto out;
1205         }
1206 #endif /* CPU_XSCALE_80200 */
1207 #if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219)
1208         if (cputype == CPU_ID_80321_400 || cputype == CPU_ID_80321_600 ||
1209             cputype == CPU_ID_80321_400_B0 || cputype == CPU_ID_80321_600_B0 ||
1210             cputype == CPU_ID_80219_400 || cputype == CPU_ID_80219_600) {
1211                 cpufuncs = xscale_cpufuncs;
1212                 cpu_reset_needs_v4_MMU_disable = 1;     /* XScale needs it */
1213                 get_cachetype_cp15();
1214                 pmap_pte_init_xscale();
1215                 goto out;
1216         }
1217 #endif /* CPU_XSCALE_80321 */
1218
1219 #if defined(CPU_XSCALE_81342)
1220         if (cputype == CPU_ID_81342) {
1221                 cpufuncs = xscalec3_cpufuncs;
1222                 cpu_reset_needs_v4_MMU_disable = 1;     /* XScale needs it */
1223                 get_cachetype_cp15();
1224                 pmap_pte_init_xscale();
1225                 goto out;
1226         }
1227 #endif /* CPU_XSCALE_81342 */
1228 #ifdef CPU_XSCALE_PXA2X0
1229         /* ignore core revision to test PXA2xx CPUs */
1230         if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA250 ||
1231             (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X ||
1232             (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA210) {
1233
1234                 cpufuncs = xscale_cpufuncs;
1235                 cpu_reset_needs_v4_MMU_disable = 1;     /* XScale needs it */
1236                 get_cachetype_cp15();
1237                 pmap_pte_init_xscale();
1238
1239                 /* Use powersave on this CPU. */
1240                 cpu_do_powersave = 1;
1241
1242                 goto out;
1243         }
1244 #endif /* CPU_XSCALE_PXA2X0 */
1245 #ifdef CPU_XSCALE_IXP425
1246         if (cputype == CPU_ID_IXP425_533 || cputype == CPU_ID_IXP425_400 ||
1247             cputype == CPU_ID_IXP425_266 || cputype == CPU_ID_IXP435) {
1248
1249                 cpufuncs = xscale_cpufuncs;
1250                 cpu_reset_needs_v4_MMU_disable = 1;     /* XScale needs it */
1251                 get_cachetype_cp15();
1252                 pmap_pte_init_xscale();
1253
1254                 goto out;
1255         }
1256 #endif /* CPU_XSCALE_IXP425 */
1257         /*
1258          * Bzzzz. And the answer was ...
1259          */
1260         panic("No support for this CPU type (%08x) in kernel", cputype);
1261         return(ARCHITECTURE_NOT_PRESENT);
1262 out:
1263         uma_set_align(arm_dcache_align_mask);
1264         return (0);
1265 }
1266
1267 /*
1268  * Fixup routines for data and prefetch aborts.
1269  *
1270  * Several compile time symbols are used
1271  *
1272  * DEBUG_FAULT_CORRECTION - Print debugging information during the
1273  * correction of registers after a fault.
1274  * ARM6_LATE_ABORT - ARM6 supports both early and late aborts
1275  * when defined should use late aborts
1276  */
1277
1278
1279 /*
1280  * Null abort fixup routine.
1281  * For use when no fixup is required.
1282  */
1283 int
1284 cpufunc_null_fixup(arg)
1285         void *arg;
1286 {
1287         return(ABORT_FIXUP_OK);
1288 }
1289
1290
1291 #if defined(CPU_ARM7TDMI)
1292
1293 #ifdef DEBUG_FAULT_CORRECTION
1294 #define DFC_PRINTF(x)           printf x
1295 #define DFC_DISASSEMBLE(x)      disassemble(x)
1296 #else
1297 #define DFC_PRINTF(x)           /* nothing */
1298 #define DFC_DISASSEMBLE(x)      /* nothing */
1299 #endif
1300
1301 /*
1302  * "Early" data abort fixup.
1303  *
1304  * For ARM2, ARM2as, ARM3 and ARM6 (in early-abort mode).  Also used
1305  * indirectly by ARM6 (in late-abort mode) and ARM7[TDMI].
1306  *
1307  * In early aborts, we may have to fix up LDM, STM, LDC and STC.
1308  */
1309 int
1310 early_abort_fixup(arg)
1311         void *arg;
1312 {
1313         trapframe_t *frame = arg;
1314         u_int fault_pc;
1315         u_int fault_instruction;
1316         int saved_lr = 0;
1317
1318         if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
1319
1320                 /* Ok an abort in SVC mode */
1321
1322                 /*
1323                  * Copy the SVC r14 into the usr r14 - The usr r14 is garbage
1324                  * as the fault happened in svc mode but we need it in the
1325                  * usr slot so we can treat the registers as an array of ints
1326                  * during fixing.
1327                  * NOTE: This PC is in the position but writeback is not
1328                  * allowed on r15.
1329                  * Doing it like this is more efficient than trapping this
1330                  * case in all possible locations in the following fixup code.
1331                  */
1332
1333                 saved_lr = frame->tf_usr_lr;
1334                 frame->tf_usr_lr = frame->tf_svc_lr;
1335
1336                 /*
1337                  * Note the trapframe does not have the SVC r13 so a fault
1338                  * from an instruction with writeback to r13 in SVC mode is
1339                  * not allowed. This should not happen as the kstack is
1340                  * always valid.
1341                  */
1342         }
1343
1344         /* Get fault address and status from the CPU */
1345
1346         fault_pc = frame->tf_pc;
1347         fault_instruction = *((volatile unsigned int *)fault_pc);
1348
1349         /* Decode the fault instruction and fix the registers as needed */
1350
1351         if ((fault_instruction & 0x0e000000) == 0x08000000) {
1352                 int base;
1353                 int loop;
1354                 int count;
1355                 int *registers = &frame->tf_r0;
1356         
1357                 DFC_PRINTF(("LDM/STM\n"));
1358                 DFC_DISASSEMBLE(fault_pc);
1359                 if (fault_instruction & (1 << 21)) {
1360                         DFC_PRINTF(("This instruction must be corrected\n"));
1361                         base = (fault_instruction >> 16) & 0x0f;
1362                         if (base == 15)
1363                                 return ABORT_FIXUP_FAILED;
1364                         /* Count registers transferred */
1365                         count = 0;
1366                         for (loop = 0; loop < 16; ++loop) {
1367                                 if (fault_instruction & (1<<loop))
1368                                         ++count;
1369                         }
1370                         DFC_PRINTF(("%d registers used\n", count));
1371                         DFC_PRINTF(("Corrected r%d by %d bytes ",
1372                                        base, count * 4));
1373                         if (fault_instruction & (1 << 23)) {
1374                                 DFC_PRINTF(("down\n"));
1375                                 registers[base] -= count * 4;
1376                         } else {
1377                                 DFC_PRINTF(("up\n"));
1378                                 registers[base] += count * 4;
1379                         }
1380                 }
1381         } else if ((fault_instruction & 0x0e000000) == 0x0c000000) {
1382                 int base;
1383                 int offset;
1384                 int *registers = &frame->tf_r0;
1385         
1386                 /* REGISTER CORRECTION IS REQUIRED FOR THESE INSTRUCTIONS */
1387
1388                 DFC_DISASSEMBLE(fault_pc);
1389
1390                 /* Only need to fix registers if write back is turned on */
1391
1392                 if ((fault_instruction & (1 << 21)) != 0) {
1393                         base = (fault_instruction >> 16) & 0x0f;
1394                         if (base == 13 &&
1395                             (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE)
1396                                 return ABORT_FIXUP_FAILED;
1397                         if (base == 15)
1398                                 return ABORT_FIXUP_FAILED;
1399
1400                         offset = (fault_instruction & 0xff) << 2;
1401                         DFC_PRINTF(("r%d=%08x\n", base, registers[base]));
1402                         if ((fault_instruction & (1 << 23)) != 0)
1403                                 offset = -offset;
1404                         registers[base] += offset;
1405                         DFC_PRINTF(("r%d=%08x\n", base, registers[base]));
1406                 }
1407         } else if ((fault_instruction & 0x0e000000) == 0x0c000000)
1408                 return ABORT_FIXUP_FAILED;
1409
1410         if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
1411
1412                 /* Ok an abort in SVC mode */
1413
1414                 /*
1415                  * Copy the SVC r14 into the usr r14 - The usr r14 is garbage
1416                  * as the fault happened in svc mode but we need it in the
1417                  * usr slot so we can treat the registers as an array of ints
1418                  * during fixing.
1419                  * NOTE: This PC is in the position but writeback is not
1420                  * allowed on r15.
1421                  * Doing it like this is more efficient than trapping this
1422                  * case in all possible locations in the prior fixup code.
1423                  */
1424
1425                 frame->tf_svc_lr = frame->tf_usr_lr;
1426                 frame->tf_usr_lr = saved_lr;
1427
1428                 /*
1429                  * Note the trapframe does not have the SVC r13 so a fault
1430                  * from an instruction with writeback to r13 in SVC mode is
1431                  * not allowed. This should not happen as the kstack is
1432                  * always valid.
1433                  */
1434         }
1435
1436         return(ABORT_FIXUP_OK);
1437 }
1438 #endif  /* CPU_ARM2/250/3/6/7 */
1439
1440
1441 #if defined(CPU_ARM7TDMI)
1442 /*
1443  * "Late" (base updated) data abort fixup
1444  *
1445  * For ARM6 (in late-abort mode) and ARM7.
1446  *
1447  * In this model, all data-transfer instructions need fixing up.  We defer
1448  * LDM, STM, LDC and STC fixup to the early-abort handler.
1449  */
1450 int
1451 late_abort_fixup(arg)
1452         void *arg;
1453 {
1454         trapframe_t *frame = arg;
1455         u_int fault_pc;
1456         u_int fault_instruction;
1457         int saved_lr = 0;
1458
1459         if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
1460
1461                 /* Ok an abort in SVC mode */
1462
1463                 /*
1464                  * Copy the SVC r14 into the usr r14 - The usr r14 is garbage
1465                  * as the fault happened in svc mode but we need it in the
1466                  * usr slot so we can treat the registers as an array of ints
1467                  * during fixing.
1468                  * NOTE: This PC is in the position but writeback is not
1469                  * allowed on r15.
1470                  * Doing it like this is more efficient than trapping this
1471                  * case in all possible locations in the following fixup code.
1472                  */
1473
1474                 saved_lr = frame->tf_usr_lr;
1475                 frame->tf_usr_lr = frame->tf_svc_lr;
1476
1477                 /*
1478                  * Note the trapframe does not have the SVC r13 so a fault
1479                  * from an instruction with writeback to r13 in SVC mode is
1480                  * not allowed. This should not happen as the kstack is
1481                  * always valid.
1482                  */
1483         }
1484
1485         /* Get fault address and status from the CPU */
1486
1487         fault_pc = frame->tf_pc;
1488         fault_instruction = *((volatile unsigned int *)fault_pc);
1489
1490         /* Decode the fault instruction and fix the registers as needed */
1491
1492         /* Was is a swap instruction ? */
1493
1494         if ((fault_instruction & 0x0fb00ff0) == 0x01000090) {
1495                 DFC_DISASSEMBLE(fault_pc);
1496         } else if ((fault_instruction & 0x0c000000) == 0x04000000) {
1497
1498                 /* Was is a ldr/str instruction */
1499                 /* This is for late abort only */
1500
1501                 int base;
1502                 int offset;
1503                 int *registers = &frame->tf_r0;
1504
1505                 DFC_DISASSEMBLE(fault_pc);
1506                 
1507                 /* This is for late abort only */
1508
1509                 if ((fault_instruction & (1 << 24)) == 0
1510                     || (fault_instruction & (1 << 21)) != 0) {  
1511                         /* postindexed ldr/str with no writeback */
1512
1513                         base = (fault_instruction >> 16) & 0x0f;
1514                         if (base == 13 &&
1515                             (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE)
1516                                 return ABORT_FIXUP_FAILED;
1517                         if (base == 15)
1518                                 return ABORT_FIXUP_FAILED;
1519                         DFC_PRINTF(("late abt fix: r%d=%08x : ",
1520                                        base, registers[base]));
1521                         if ((fault_instruction & (1 << 25)) == 0) {
1522                                 /* Immediate offset - easy */
1523
1524                                 offset = fault_instruction & 0xfff;
1525                                 if ((fault_instruction & (1 << 23)))
1526                                         offset = -offset;
1527                                 registers[base] += offset;
1528                                 DFC_PRINTF(("imm=%08x ", offset));
1529                         } else {
1530                                 /* offset is a shifted register */
1531                                 int shift;
1532
1533                                 offset = fault_instruction & 0x0f;
1534                                 if (offset == base)
1535                                         return ABORT_FIXUP_FAILED;
1536                 
1537                                 /*
1538                                  * Register offset - hard we have to
1539                                  * cope with shifts !
1540                                  */
1541                                 offset = registers[offset];
1542
1543                                 if ((fault_instruction & (1 << 4)) == 0)
1544                                         /* shift with amount */
1545                                         shift = (fault_instruction >> 7) & 0x1f;
1546                                 else {
1547                                         /* shift with register */
1548                                         if ((fault_instruction & (1 << 7)) != 0)
1549                                                 /* undefined for now so bail out */
1550                                                 return ABORT_FIXUP_FAILED;
1551                                         shift = ((fault_instruction >> 8) & 0xf);
1552                                         if (base == shift)
1553                                                 return ABORT_FIXUP_FAILED;
1554                                         DFC_PRINTF(("shift reg=%d ", shift));
1555                                         shift = registers[shift];
1556                                 }
1557                                 DFC_PRINTF(("shift=%08x ", shift));
1558                                 switch (((fault_instruction >> 5) & 0x3)) {
1559                                 case 0 : /* Logical left */
1560                                         offset = (int)(((u_int)offset) << shift);
1561                                         break;
1562                                 case 1 : /* Logical Right */
1563                                         if (shift == 0) shift = 32;
1564                                         offset = (int)(((u_int)offset) >> shift);
1565                                         break;
1566                                 case 2 : /* Arithmetic Right */
1567                                         if (shift == 0) shift = 32;
1568                                         offset = (int)(((int)offset) >> shift);
1569                                         break;
1570                                 case 3 : /* Rotate right (rol or rxx) */
1571                                         return ABORT_FIXUP_FAILED;
1572                                         break;
1573                                 }
1574
1575                                 DFC_PRINTF(("abt: fixed LDR/STR with "
1576                                                "register offset\n"));
1577                                 if ((fault_instruction & (1 << 23)))
1578                                         offset = -offset;
1579                                 DFC_PRINTF(("offset=%08x ", offset));
1580                                 registers[base] += offset;
1581                         }
1582                         DFC_PRINTF(("r%d=%08x\n", base, registers[base]));
1583                 }
1584         }
1585
1586         if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
1587
1588                 /* Ok an abort in SVC mode */
1589
1590                 /*
1591                  * Copy the SVC r14 into the usr r14 - The usr r14 is garbage
1592                  * as the fault happened in svc mode but we need it in the
1593                  * usr slot so we can treat the registers as an array of ints
1594                  * during fixing.
1595                  * NOTE: This PC is in the position but writeback is not
1596                  * allowed on r15.
1597                  * Doing it like this is more efficient than trapping this
1598                  * case in all possible locations in the prior fixup code.
1599                  */
1600
1601                 frame->tf_svc_lr = frame->tf_usr_lr;
1602                 frame->tf_usr_lr = saved_lr;
1603
1604                 /*
1605                  * Note the trapframe does not have the SVC r13 so a fault
1606                  * from an instruction with writeback to r13 in SVC mode is
1607                  * not allowed. This should not happen as the kstack is
1608                  * always valid.
1609                  */
1610         }
1611
1612         /*
1613          * Now let the early-abort fixup routine have a go, in case it
1614          * was an LDM, STM, LDC or STC that faulted.
1615          */
1616
1617         return early_abort_fixup(arg);
1618 }
1619 #endif  /* CPU_ARM7TDMI */
1620
1621 /*
1622  * CPU Setup code
1623  */
1624
1625 #if defined(CPU_ARM7TDMI) || defined(CPU_ARM8) || defined (CPU_ARM9) || \
1626   defined(CPU_ARM9E) || \
1627   defined(CPU_SA110) || defined(CPU_SA1100) || defined(CPU_SA1110) ||   \
1628   defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) ||             \
1629   defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) ||           \
1630   defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \
1631   defined(CPU_ARM10) ||  defined(CPU_ARM11) || \
1632   defined(CPU_FA526)
1633
1634 #define IGN     0
1635 #define OR      1
1636 #define BIC     2
1637
1638 struct cpu_option {
1639         char    *co_name;
1640         int     co_falseop;
1641         int     co_trueop;
1642         int     co_value;
1643 };
1644
1645 static u_int parse_cpu_options(char *, struct cpu_option *, u_int);
1646
1647 static u_int
1648 parse_cpu_options(args, optlist, cpuctrl)
1649         char *args;
1650         struct cpu_option *optlist;    
1651         u_int cpuctrl; 
1652 {
1653         int integer;
1654
1655         if (args == NULL)
1656                 return(cpuctrl);
1657
1658         while (optlist->co_name) {
1659                 if (get_bootconf_option(args, optlist->co_name,
1660                     BOOTOPT_TYPE_BOOLEAN, &integer)) {
1661                         if (integer) {
1662                                 if (optlist->co_trueop == OR)
1663                                         cpuctrl |= optlist->co_value;
1664                                 else if (optlist->co_trueop == BIC)
1665                                         cpuctrl &= ~optlist->co_value;
1666                         } else {
1667                                 if (optlist->co_falseop == OR)
1668                                         cpuctrl |= optlist->co_value;
1669                                 else if (optlist->co_falseop == BIC)
1670                                         cpuctrl &= ~optlist->co_value;
1671                         }
1672                 }
1673                 ++optlist;
1674         }
1675         return(cpuctrl);
1676 }
1677 #endif /* CPU_ARM7TDMI || CPU_ARM8 || CPU_SA110 || XSCALE*/
1678
1679 #if defined(CPU_ARM7TDMI) || defined(CPU_ARM8)
1680 struct cpu_option arm678_options[] = {
1681 #ifdef COMPAT_12
1682         { "nocache",            IGN, BIC, CPU_CONTROL_IDC_ENABLE },
1683         { "nowritebuf",         IGN, BIC, CPU_CONTROL_WBUF_ENABLE },
1684 #endif  /* COMPAT_12 */
1685         { "cpu.cache",          BIC, OR,  CPU_CONTROL_IDC_ENABLE },
1686         { "cpu.nocache",        OR,  BIC, CPU_CONTROL_IDC_ENABLE },
1687         { "cpu.writebuf",       BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1688         { "cpu.nowritebuf",     OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1689         { NULL,                 IGN, IGN, 0 }
1690 };
1691
1692 #endif  /* CPU_ARM6 || CPU_ARM7 || CPU_ARM7TDMI || CPU_ARM8 */
1693
1694 #ifdef CPU_ARM7TDMI
1695 struct cpu_option arm7tdmi_options[] = {
1696         { "arm7.cache",         BIC, OR,  CPU_CONTROL_IDC_ENABLE },
1697         { "arm7.nocache",       OR,  BIC, CPU_CONTROL_IDC_ENABLE },
1698         { "arm7.writebuf",      BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1699         { "arm7.nowritebuf",    OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1700 #ifdef COMPAT_12
1701         { "fpaclk2",            BIC, OR,  CPU_CONTROL_CPCLK },
1702 #endif  /* COMPAT_12 */
1703         { "arm700.fpaclk",      BIC, OR,  CPU_CONTROL_CPCLK },
1704         { NULL,                 IGN, IGN, 0 }
1705 };
1706
1707 void
1708 arm7tdmi_setup(args)
1709         char *args;
1710 {
1711         int cpuctrl;
1712
1713         cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1714                  | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1715                  | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE;
1716
1717         cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl);
1718         cpuctrl = parse_cpu_options(args, arm7tdmi_options, cpuctrl);
1719
1720 #ifdef __ARMEB__
1721         cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1722 #endif
1723
1724         /* Clear out the cache */
1725         cpu_idcache_wbinv_all();
1726
1727         /* Set the control register */
1728         ctrl = cpuctrl;
1729         cpu_control(0xffffffff, cpuctrl);
1730 }
1731 #endif  /* CPU_ARM7TDMI */
1732
1733 #ifdef CPU_ARM8
1734 struct cpu_option arm8_options[] = {
1735         { "arm8.cache",         BIC, OR,  CPU_CONTROL_IDC_ENABLE },
1736         { "arm8.nocache",       OR,  BIC, CPU_CONTROL_IDC_ENABLE },
1737         { "arm8.writebuf",      BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1738         { "arm8.nowritebuf",    OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1739 #ifdef COMPAT_12
1740         { "branchpredict",      BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
1741 #endif  /* COMPAT_12 */
1742         { "cpu.branchpredict",  BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
1743         { "arm8.branchpredict", BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
1744         { NULL,                 IGN, IGN, 0 }
1745 };
1746
1747 void
1748 arm8_setup(args)
1749         char *args;
1750 {
1751         int integer;
1752         int cpuctrl, cpuctrlmask;
1753         int clocktest;
1754         int setclock = 0;
1755
1756         cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1757                  | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1758                  | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE;
1759         cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1760                  | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1761                  | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE
1762                  | CPU_CONTROL_BPRD_ENABLE | CPU_CONTROL_ROM_ENABLE
1763                  | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE;
1764
1765 #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1766         cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1767 #endif
1768
1769         cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl);
1770         cpuctrl = parse_cpu_options(args, arm8_options, cpuctrl);
1771
1772 #ifdef __ARMEB__
1773         cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1774 #endif
1775
1776         /* Get clock configuration */
1777         clocktest = arm8_clock_config(0, 0) & 0x0f;
1778
1779         /* Special ARM8 clock and test configuration */
1780         if (get_bootconf_option(args, "arm8.clock.reset", BOOTOPT_TYPE_BOOLEAN, &integer)) {
1781                 clocktest = 0;
1782                 setclock = 1;
1783         }
1784         if (get_bootconf_option(args, "arm8.clock.dynamic", BOOTOPT_TYPE_BOOLEAN, &integer)) {
1785                 if (integer)
1786                         clocktest |= 0x01;
1787                 else
1788                         clocktest &= ~(0x01);
1789                 setclock = 1;
1790         }
1791         if (get_bootconf_option(args, "arm8.clock.sync", BOOTOPT_TYPE_BOOLEAN, &integer)) {
1792                 if (integer)
1793                         clocktest |= 0x02;
1794                 else
1795                         clocktest &= ~(0x02);
1796                 setclock = 1;
1797         }
1798         if (get_bootconf_option(args, "arm8.clock.fast", BOOTOPT_TYPE_BININT, &integer)) {
1799                 clocktest = (clocktest & ~0xc0) | (integer & 3) << 2;
1800                 setclock = 1;
1801         }
1802         if (get_bootconf_option(args, "arm8.test", BOOTOPT_TYPE_BININT, &integer)) {
1803                 clocktest |= (integer & 7) << 5;
1804                 setclock = 1;
1805         }
1806         
1807         /* Clear out the cache */
1808         cpu_idcache_wbinv_all();
1809
1810         /* Set the control register */
1811         ctrl = cpuctrl;
1812         cpu_control(0xffffffff, cpuctrl);
1813
1814         /* Set the clock/test register */    
1815         if (setclock)
1816                 arm8_clock_config(0x7f, clocktest);
1817 }
1818 #endif  /* CPU_ARM8 */
1819
1820 #ifdef CPU_ARM9
1821 struct cpu_option arm9_options[] = {
1822         { "cpu.cache",          BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1823         { "cpu.nocache",        OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1824         { "arm9.cache", BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1825         { "arm9.icache",        BIC, OR,  CPU_CONTROL_IC_ENABLE },
1826         { "arm9.dcache",        BIC, OR,  CPU_CONTROL_DC_ENABLE },
1827         { "cpu.writebuf",       BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1828         { "cpu.nowritebuf",     OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1829         { "arm9.writebuf",      BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1830         { NULL,                 IGN, IGN, 0 }
1831 };
1832
1833 void
1834 arm9_setup(args)
1835         char *args;
1836 {
1837         int cpuctrl, cpuctrlmask;
1838
1839         cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1840             | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1841             | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1842             | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE |
1843             CPU_CONTROL_ROUNDROBIN;
1844         cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
1845                  | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
1846                  | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1847                  | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
1848                  | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
1849                  | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_VECRELOC
1850                  | CPU_CONTROL_ROUNDROBIN;
1851
1852 #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1853         cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1854 #endif
1855
1856         cpuctrl = parse_cpu_options(args, arm9_options, cpuctrl);
1857
1858 #ifdef __ARMEB__
1859         cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1860 #endif
1861         if (vector_page == ARM_VECTORS_HIGH)
1862                 cpuctrl |= CPU_CONTROL_VECRELOC;
1863
1864         /* Clear out the cache */
1865         cpu_idcache_wbinv_all();
1866
1867         /* Set the control register */
1868         cpu_control(cpuctrlmask, cpuctrl);
1869         ctrl = cpuctrl;
1870
1871 }
1872 #endif  /* CPU_ARM9 */
1873
1874 #if defined(CPU_ARM9E) || defined(CPU_ARM10)
1875 struct cpu_option arm10_options[] = {
1876         { "cpu.cache",          BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1877         { "cpu.nocache",        OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1878         { "arm10.cache",        BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1879         { "arm10.icache",       BIC, OR,  CPU_CONTROL_IC_ENABLE },
1880         { "arm10.dcache",       BIC, OR,  CPU_CONTROL_DC_ENABLE },
1881         { "cpu.writebuf",       BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1882         { "cpu.nowritebuf",     OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1883         { "arm10.writebuf",     BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1884         { NULL,                 IGN, IGN, 0 }
1885 };
1886
1887 void
1888 arm10_setup(args)
1889         char *args;
1890 {
1891         int cpuctrl, cpuctrlmask;
1892
1893         cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
1894             | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 
1895             | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE;
1896         cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
1897             | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1898             | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
1899             | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
1900             | CPU_CONTROL_BPRD_ENABLE
1901             | CPU_CONTROL_ROUNDROBIN | CPU_CONTROL_CPCLK;
1902
1903 #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1904         cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1905 #endif
1906
1907         cpuctrl = parse_cpu_options(args, arm10_options, cpuctrl);
1908
1909 #ifdef __ARMEB__
1910         cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1911 #endif
1912
1913         /* Clear out the cache */
1914         cpu_idcache_wbinv_all();
1915
1916         /* Now really make sure they are clean.  */
1917         __asm __volatile ("mcr\tp15, 0, r0, c7, c7, 0" : : );
1918
1919         if (vector_page == ARM_VECTORS_HIGH)
1920                 cpuctrl |= CPU_CONTROL_VECRELOC;
1921
1922         /* Set the control register */
1923         ctrl = cpuctrl;
1924         cpu_control(0xffffffff, cpuctrl);
1925
1926         /* And again. */
1927         cpu_idcache_wbinv_all();
1928 }
1929 #endif  /* CPU_ARM9E || CPU_ARM10 */
1930
1931 #ifdef CPU_ARM11
1932 struct cpu_option arm11_options[] = {
1933         { "cpu.cache",          BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1934         { "cpu.nocache",        OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1935         { "arm11.cache",        BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1936         { "arm11.icache",       BIC, OR,  CPU_CONTROL_IC_ENABLE },
1937         { "arm11.dcache",       BIC, OR,  CPU_CONTROL_DC_ENABLE },
1938         { NULL,                 IGN, IGN, 0 }
1939 };
1940
1941 void
1942 arm11_setup(args)
1943         char *args;
1944 {
1945         int cpuctrl, cpuctrlmask;
1946
1947         cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
1948             | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1949             /* | CPU_CONTROL_BPRD_ENABLE */;
1950         cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
1951             | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
1952             | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_BPRD_ENABLE
1953             | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
1954             | CPU_CONTROL_ROUNDROBIN | CPU_CONTROL_CPCLK;
1955
1956 #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
1957         cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
1958 #endif
1959
1960         cpuctrl = parse_cpu_options(args, arm11_options, cpuctrl);
1961
1962 #ifdef __ARMEB__
1963         cpuctrl |= CPU_CONTROL_BEND_ENABLE;
1964 #endif
1965
1966         /* Clear out the cache */
1967         cpu_idcache_wbinv_all();
1968
1969         /* Now really make sure they are clean.  */
1970         __asm __volatile ("mcr\tp15, 0, r0, c7, c7, 0" : : );
1971
1972         /* Set the control register */
1973         curcpu()->ci_ctrl = cpuctrl;
1974         cpu_control(0xffffffff, cpuctrl);
1975
1976         /* And again. */
1977         cpu_idcache_wbinv_all();
1978 }
1979 #endif  /* CPU_ARM11 */
1980
1981 #ifdef CPU_SA110
1982 struct cpu_option sa110_options[] = {
1983 #ifdef COMPAT_12
1984         { "nocache",            IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1985         { "nowritebuf",         IGN, BIC, CPU_CONTROL_WBUF_ENABLE },
1986 #endif  /* COMPAT_12 */
1987         { "cpu.cache",          BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1988         { "cpu.nocache",        OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1989         { "sa110.cache",        BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
1990         { "sa110.icache",       BIC, OR,  CPU_CONTROL_IC_ENABLE },
1991         { "sa110.dcache",       BIC, OR,  CPU_CONTROL_DC_ENABLE },
1992         { "cpu.writebuf",       BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1993         { "cpu.nowritebuf",     OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
1994         { "sa110.writebuf",     BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
1995         { NULL,                 IGN, IGN, 0 }
1996 };
1997
1998 void
1999 sa110_setup(args)
2000         char *args;
2001 {
2002         int cpuctrl, cpuctrlmask;
2003
2004         cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2005                  | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2006                  | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2007                  | CPU_CONTROL_WBUF_ENABLE;
2008         cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2009                  | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2010                  | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2011                  | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
2012                  | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
2013                  | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
2014                  | CPU_CONTROL_CPCLK;
2015
2016 #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2017         cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2018 #endif
2019
2020         cpuctrl = parse_cpu_options(args, sa110_options, cpuctrl);
2021
2022 #ifdef __ARMEB__
2023         cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2024 #endif
2025
2026         /* Clear out the cache */
2027         cpu_idcache_wbinv_all();
2028
2029         /* Set the control register */
2030         ctrl = cpuctrl;
2031 /*      cpu_control(cpuctrlmask, cpuctrl);*/
2032         cpu_control(0xffffffff, cpuctrl);
2033
2034         /* 
2035          * enable clockswitching, note that this doesn't read or write to r0,
2036          * r0 is just to make it valid asm
2037          */
2038         __asm ("mcr 15, 0, r0, c15, c1, 2");
2039 }
2040 #endif  /* CPU_SA110 */
2041
2042 #if defined(CPU_SA1100) || defined(CPU_SA1110)
2043 struct cpu_option sa11x0_options[] = {
2044 #ifdef COMPAT_12
2045         { "nocache",            IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2046         { "nowritebuf",         IGN, BIC, CPU_CONTROL_WBUF_ENABLE },
2047 #endif  /* COMPAT_12 */
2048         { "cpu.cache",          BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2049         { "cpu.nocache",        OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2050         { "sa11x0.cache",       BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2051         { "sa11x0.icache",      BIC, OR,  CPU_CONTROL_IC_ENABLE },
2052         { "sa11x0.dcache",      BIC, OR,  CPU_CONTROL_DC_ENABLE },
2053         { "cpu.writebuf",       BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2054         { "cpu.nowritebuf",     OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
2055         { "sa11x0.writebuf",    BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2056         { NULL,                 IGN, IGN, 0 }
2057 };
2058
2059 void
2060 sa11x0_setup(args)
2061         char *args;
2062 {
2063         int cpuctrl, cpuctrlmask;
2064
2065         cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2066                  | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2067                  | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2068                  | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE;
2069         cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2070                  | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2071                  | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2072                  | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
2073                  | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
2074                  | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
2075                  | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC;
2076
2077 #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2078         cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2079 #endif
2080
2081
2082         cpuctrl = parse_cpu_options(args, sa11x0_options, cpuctrl);
2083
2084 #ifdef __ARMEB__
2085         cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2086 #endif
2087
2088         if (vector_page == ARM_VECTORS_HIGH)
2089                 cpuctrl |= CPU_CONTROL_VECRELOC;
2090         /* Clear out the cache */
2091         cpu_idcache_wbinv_all();
2092         /* Set the control register */    
2093         ctrl = cpuctrl;
2094         cpu_control(0xffffffff, cpuctrl);
2095 }
2096 #endif  /* CPU_SA1100 || CPU_SA1110 */
2097
2098 #if defined(CPU_FA526)
2099 struct cpu_option fa526_options[] = {
2100 #ifdef COMPAT_12
2101         { "nocache",            IGN, BIC, (CPU_CONTROL_IC_ENABLE |
2102                                            CPU_CONTROL_DC_ENABLE) },
2103         { "nowritebuf",         IGN, BIC, CPU_CONTROL_WBUF_ENABLE },
2104 #endif  /* COMPAT_12 */
2105         { "cpu.cache",          BIC, OR,  (CPU_CONTROL_IC_ENABLE |
2106                                            CPU_CONTROL_DC_ENABLE) },
2107         { "cpu.nocache",        OR,  BIC, (CPU_CONTROL_IC_ENABLE |
2108                                            CPU_CONTROL_DC_ENABLE) },
2109         { "cpu.writebuf",       BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2110         { "cpu.nowritebuf",     OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
2111         { NULL,                 IGN, IGN, 0 }
2112 };
2113
2114 void
2115 fa526_setup(char *args)
2116 {
2117         int cpuctrl, cpuctrlmask;
2118
2119         cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2120                  | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2121                  | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2122                  | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
2123                 | CPU_CONTROL_BPRD_ENABLE;
2124         cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2125                  | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2126                  | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2127                  | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
2128                  | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
2129                  | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
2130                  | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC;
2131
2132 #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2133         cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2134 #endif
2135
2136         cpuctrl = parse_cpu_options(args, fa526_options, cpuctrl);
2137
2138 #ifdef __ARMEB__
2139         cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2140 #endif
2141
2142         if (vector_page == ARM_VECTORS_HIGH)
2143                 cpuctrl |= CPU_CONTROL_VECRELOC;
2144
2145         /* Clear out the cache */
2146         cpu_idcache_wbinv_all();
2147
2148         /* Set the control register */
2149         ctrl = cpuctrl;
2150         cpu_control(0xffffffff, cpuctrl);
2151 }
2152 #endif  /* CPU_FA526 */
2153
2154 #if defined(CPU_IXP12X0)
2155 struct cpu_option ixp12x0_options[] = {
2156         { "cpu.cache",          BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2157         { "cpu.nocache",        OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2158         { "ixp12x0.cache",      BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2159         { "ixp12x0.icache",     BIC, OR,  CPU_CONTROL_IC_ENABLE },
2160         { "ixp12x0.dcache",     BIC, OR,  CPU_CONTROL_DC_ENABLE },
2161         { "cpu.writebuf",       BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2162         { "cpu.nowritebuf",     OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
2163         { "ixp12x0.writebuf",   BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
2164         { NULL,                 IGN, IGN, 0 }
2165 };
2166
2167 void
2168 ixp12x0_setup(args)
2169         char *args;
2170 {
2171         int cpuctrl, cpuctrlmask;
2172
2173
2174         cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE
2175                  | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_SYST_ENABLE
2176                  | CPU_CONTROL_IC_ENABLE;
2177
2178         cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_AFLT_ENABLE
2179                  | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE
2180                  | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_SYST_ENABLE
2181                  | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_IC_ENABLE
2182                  | CPU_CONTROL_VECRELOC;
2183
2184 #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2185         cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2186 #endif
2187
2188         cpuctrl = parse_cpu_options(args, ixp12x0_options, cpuctrl);
2189
2190 #ifdef __ARMEB__
2191         cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2192 #endif
2193
2194         if (vector_page == ARM_VECTORS_HIGH)
2195                 cpuctrl |= CPU_CONTROL_VECRELOC;
2196
2197         /* Clear out the cache */
2198         cpu_idcache_wbinv_all();
2199
2200         /* Set the control register */    
2201         ctrl = cpuctrl;
2202         /* cpu_control(0xffffffff, cpuctrl); */
2203         cpu_control(cpuctrlmask, cpuctrl);
2204 }
2205 #endif /* CPU_IXP12X0 */
2206
2207 #if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
2208   defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
2209   defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)
2210 struct cpu_option xscale_options[] = {
2211 #ifdef COMPAT_12
2212         { "branchpredict",      BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
2213         { "nocache",            IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2214 #endif  /* COMPAT_12 */
2215         { "cpu.branchpredict",  BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
2216         { "cpu.cache",          BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2217         { "cpu.nocache",        OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2218         { "xscale.branchpredict", BIC, OR,  CPU_CONTROL_BPRD_ENABLE },
2219         { "xscale.cache",       BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
2220         { "xscale.icache",      BIC, OR,  CPU_CONTROL_IC_ENABLE },
2221         { "xscale.dcache",      BIC, OR,  CPU_CONTROL_DC_ENABLE },
2222         { NULL,                 IGN, IGN, 0 }
2223 };
2224
2225 void
2226 xscale_setup(args)
2227         char *args;
2228 {
2229         uint32_t auxctl;
2230         int cpuctrl, cpuctrlmask;
2231
2232         /*
2233          * The XScale Write Buffer is always enabled.  Our option
2234          * is to enable/disable coalescing.  Note that bits 6:3
2235          * must always be enabled.
2236          */
2237
2238         cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2239                  | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2240                  | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2241                  | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
2242                  | CPU_CONTROL_BPRD_ENABLE;
2243         cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
2244                  | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
2245                  | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
2246                  | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
2247                  | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE
2248                  | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE
2249                  | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC | \
2250                  CPU_CONTROL_L2_ENABLE;
2251
2252 #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
2253         cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
2254 #endif
2255
2256         cpuctrl = parse_cpu_options(args, xscale_options, cpuctrl);
2257
2258 #ifdef __ARMEB__
2259         cpuctrl |= CPU_CONTROL_BEND_ENABLE;
2260 #endif
2261
2262         if (vector_page == ARM_VECTORS_HIGH)
2263                 cpuctrl |= CPU_CONTROL_VECRELOC;
2264 #ifdef CPU_XSCALE_CORE3
2265         cpuctrl |= CPU_CONTROL_L2_ENABLE;
2266 #endif
2267
2268         /* Clear out the cache */
2269         cpu_idcache_wbinv_all();
2270
2271         /*
2272          * Set the control register.  Note that bits 6:3 must always
2273          * be set to 1.
2274          */
2275         ctrl = cpuctrl;
2276 /*      cpu_control(cpuctrlmask, cpuctrl);*/
2277         cpu_control(0xffffffff, cpuctrl);
2278
2279         /* Make sure write coalescing is turned on */
2280         __asm __volatile("mrc p15, 0, %0, c1, c0, 1"
2281                 : "=r" (auxctl));
2282 #ifdef XSCALE_NO_COALESCE_WRITES
2283         auxctl |= XSCALE_AUXCTL_K;
2284 #else
2285         auxctl &= ~XSCALE_AUXCTL_K;
2286 #endif
2287 #ifdef CPU_XSCALE_CORE3
2288         auxctl |= XSCALE_AUXCTL_LLR;
2289         auxctl |= XSCALE_AUXCTL_MD_MASK;
2290 #endif
2291         __asm __volatile("mcr p15, 0, %0, c1, c0, 1"
2292                 : : "r" (auxctl));
2293 }
2294 #endif  /* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 
2295            CPU_XSCALE_80219 */