cpufunc.c revision 146619
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: head/sys/arm/arm/cpufunc.c 146619 2005-05-25 13:46:32Z cognet $"); 49 50#include <sys/cdefs.h> 51 52#include <sys/types.h> 53#include <sys/param.h> 54#include <sys/systm.h> 55#include <sys/lock.h> 56#include <sys/mutex.h> 57#include <sys/bus.h> 58#include <machine/bus.h> 59#include <machine/cpu.h> 60#include <machine/disassem.h> 61 62#include <vm/vm.h> 63#include <vm/pmap.h> 64 65#include <machine/cpuconf.h> 66#include <machine/cpufunc.h> 67#include <machine/bootconfig.h> 68 69#ifdef CPU_XSCALE_80200 70#include <arm/xscale/i80200/i80200reg.h> 71#include <arm/xscale/i80200/i80200var.h> 72#endif 73 74#ifdef CPU_XSCALE_80321 75#include <arm/xscale/i80321/i80321reg.h> 76#include <arm/xscale/i80321/i80321var.h> 77#endif 78 79#ifdef CPU_XSCALE_IXP425 80#include <arm/xscale/ixp425/ixp425reg.h> 81#include <arm/xscale/ixp425/ixp425var.h> 82#endif 83 84#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) 85#include <arm/xscale/xscalereg.h> 86#endif 87 88#if defined(PERFCTRS) 89struct arm_pmc_funcs *arm_pmc; 90#endif 91 92/* PRIMARY CACHE VARIABLES */ 93int arm_picache_size; 94int arm_picache_line_size; 95int arm_picache_ways; 96 97int arm_pdcache_size; /* and unified */ 98int arm_pdcache_line_size; 99int arm_pdcache_ways; 100 101int arm_pcache_type; 102int arm_pcache_unified; 103 104int arm_dcache_align; 105int arm_dcache_align_mask; 106 107/* 1 == use cpu_sleep(), 0 == don't */ 108int cpu_do_powersave; 109int ctrl; 110 111#ifdef CPU_ARM7TDMI 112struct cpu_functions arm7tdmi_cpufuncs = { 113 /* CPU functions */ 114 115 cpufunc_id, /* id */ 116 cpufunc_nullop, /* cpwait */ 117 118 /* MMU functions */ 119 120 cpufunc_control, /* control */ 121 cpufunc_domains, /* domain */ 122 arm7tdmi_setttb, /* setttb */ 123 cpufunc_faultstatus, /* faultstatus */ 124 cpufunc_faultaddress, /* faultaddress */ 125 126 /* TLB functions */ 127 128 arm7tdmi_tlb_flushID, /* tlb_flushID */ 129 arm7tdmi_tlb_flushID_SE, /* tlb_flushID_SE */ 130 arm7tdmi_tlb_flushID, /* tlb_flushI */ 131 arm7tdmi_tlb_flushID_SE, /* tlb_flushI_SE */ 132 arm7tdmi_tlb_flushID, /* tlb_flushD */ 133 arm7tdmi_tlb_flushID_SE, /* tlb_flushD_SE */ 134 135 /* Cache operations */ 136 137 cpufunc_nullop, /* icache_sync_all */ 138 (void *)cpufunc_nullop, /* icache_sync_range */ 139 140 arm7tdmi_cache_flushID, /* dcache_wbinv_all */ 141 (void *)arm7tdmi_cache_flushID, /* dcache_wbinv_range */ 142 (void *)arm7tdmi_cache_flushID, /* dcache_inv_range */ 143 (void *)cpufunc_nullop, /* dcache_wb_range */ 144 145 arm7tdmi_cache_flushID, /* idcache_wbinv_all */ 146 (void *)arm7tdmi_cache_flushID, /* idcache_wbinv_range */ 147 148 /* Other functions */ 149 150 cpufunc_nullop, /* flush_prefetchbuf */ 151 cpufunc_nullop, /* drain_writebuf */ 152 cpufunc_nullop, /* flush_brnchtgt_C */ 153 (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 154 155 (void *)cpufunc_nullop, /* sleep */ 156 157 /* Soft functions */ 158 159 late_abort_fixup, /* dataabt_fixup */ 160 cpufunc_null_fixup, /* prefetchabt_fixup */ 161 162 arm7tdmi_context_switch, /* context_switch */ 163 164 arm7tdmi_setup /* cpu setup */ 165 166}; 167#endif /* CPU_ARM7TDMI */ 168 169#ifdef CPU_ARM8 170struct cpu_functions arm8_cpufuncs = { 171 /* CPU functions */ 172 173 cpufunc_id, /* id */ 174 cpufunc_nullop, /* cpwait */ 175 176 /* MMU functions */ 177 178 cpufunc_control, /* control */ 179 cpufunc_domains, /* domain */ 180 arm8_setttb, /* setttb */ 181 cpufunc_faultstatus, /* faultstatus */ 182 cpufunc_faultaddress, /* faultaddress */ 183 184 /* TLB functions */ 185 186 arm8_tlb_flushID, /* tlb_flushID */ 187 arm8_tlb_flushID_SE, /* tlb_flushID_SE */ 188 arm8_tlb_flushID, /* tlb_flushI */ 189 arm8_tlb_flushID_SE, /* tlb_flushI_SE */ 190 arm8_tlb_flushID, /* tlb_flushD */ 191 arm8_tlb_flushID_SE, /* tlb_flushD_SE */ 192 193 /* Cache operations */ 194 195 cpufunc_nullop, /* icache_sync_all */ 196 (void *)cpufunc_nullop, /* icache_sync_range */ 197 198 arm8_cache_purgeID, /* dcache_wbinv_all */ 199 (void *)arm8_cache_purgeID, /* dcache_wbinv_range */ 200/*XXX*/ (void *)arm8_cache_purgeID, /* dcache_inv_range */ 201 (void *)arm8_cache_cleanID, /* dcache_wb_range */ 202 203 arm8_cache_purgeID, /* idcache_wbinv_all */ 204 (void *)arm8_cache_purgeID, /* idcache_wbinv_range */ 205 206 /* Other functions */ 207 208 cpufunc_nullop, /* flush_prefetchbuf */ 209 cpufunc_nullop, /* drain_writebuf */ 210 cpufunc_nullop, /* flush_brnchtgt_C */ 211 (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 212 213 (void *)cpufunc_nullop, /* sleep */ 214 215 /* Soft functions */ 216 217 cpufunc_null_fixup, /* dataabt_fixup */ 218 cpufunc_null_fixup, /* prefetchabt_fixup */ 219 220 arm8_context_switch, /* context_switch */ 221 222 arm8_setup /* cpu setup */ 223}; 224#endif /* CPU_ARM8 */ 225 226#ifdef CPU_ARM9 227struct cpu_functions arm9_cpufuncs = { 228 /* CPU functions */ 229 230 cpufunc_id, /* id */ 231 cpufunc_nullop, /* cpwait */ 232 233 /* MMU functions */ 234 235 cpufunc_control, /* control */ 236 cpufunc_domains, /* Domain */ 237 arm9_setttb, /* Setttb */ 238 cpufunc_faultstatus, /* Faultstatus */ 239 cpufunc_faultaddress, /* Faultaddress */ 240 241 /* TLB functions */ 242 243 armv4_tlb_flushID, /* tlb_flushID */ 244 arm9_tlb_flushID_SE, /* tlb_flushID_SE */ 245 armv4_tlb_flushI, /* tlb_flushI */ 246 (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ 247 armv4_tlb_flushD, /* tlb_flushD */ 248 armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 249 250 /* Cache operations */ 251 252 arm9_icache_sync_all, /* icache_sync_all */ 253 arm9_icache_sync_range, /* icache_sync_range */ 254 255 arm9_dcache_wbinv_all, /* dcache_wbinv_all */ 256 arm9_dcache_wbinv_range, /* dcache_wbinv_range */ 257/*XXX*/ arm9_dcache_wbinv_range, /* dcache_inv_range */ 258 arm9_dcache_wb_range, /* dcache_wb_range */ 259 260 arm9_idcache_wbinv_all, /* idcache_wbinv_all */ 261 arm9_idcache_wbinv_range, /* idcache_wbinv_range */ 262 263 /* Other functions */ 264 265 cpufunc_nullop, /* flush_prefetchbuf */ 266 armv4_drain_writebuf, /* drain_writebuf */ 267 cpufunc_nullop, /* flush_brnchtgt_C */ 268 (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 269 270 (void *)cpufunc_nullop, /* sleep */ 271 272 /* Soft functions */ 273 274 cpufunc_null_fixup, /* dataabt_fixup */ 275 cpufunc_null_fixup, /* prefetchabt_fixup */ 276 277 arm9_context_switch, /* context_switch */ 278 279 arm9_setup /* cpu setup */ 280 281}; 282#endif /* CPU_ARM9 */ 283 284#ifdef CPU_ARM10 285struct cpu_functions arm10_cpufuncs = { 286 /* CPU functions */ 287 288 cpufunc_id, /* id */ 289 cpufunc_nullop, /* cpwait */ 290 291 /* MMU functions */ 292 293 cpufunc_control, /* control */ 294 cpufunc_domains, /* Domain */ 295 arm10_setttb, /* Setttb */ 296 cpufunc_faultstatus, /* Faultstatus */ 297 cpufunc_faultaddress, /* Faultaddress */ 298 299 /* TLB functions */ 300 301 armv4_tlb_flushID, /* tlb_flushID */ 302 arm10_tlb_flushID_SE, /* tlb_flushID_SE */ 303 armv4_tlb_flushI, /* tlb_flushI */ 304 arm10_tlb_flushI_SE, /* tlb_flushI_SE */ 305 armv4_tlb_flushD, /* tlb_flushD */ 306 armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 307 308 /* Cache operations */ 309 310 arm10_icache_sync_all, /* icache_sync_all */ 311 arm10_icache_sync_range, /* icache_sync_range */ 312 313 arm10_dcache_wbinv_all, /* dcache_wbinv_all */ 314 arm10_dcache_wbinv_range, /* dcache_wbinv_range */ 315 arm10_dcache_inv_range, /* dcache_inv_range */ 316 arm10_dcache_wb_range, /* dcache_wb_range */ 317 318 arm10_idcache_wbinv_all, /* idcache_wbinv_all */ 319 arm10_idcache_wbinv_range, /* idcache_wbinv_range */ 320 321 /* Other functions */ 322 323 cpufunc_nullop, /* flush_prefetchbuf */ 324 armv4_drain_writebuf, /* drain_writebuf */ 325 cpufunc_nullop, /* flush_brnchtgt_C */ 326 (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 327 328 (void *)cpufunc_nullop, /* sleep */ 329 330 /* Soft functions */ 331 332 cpufunc_null_fixup, /* dataabt_fixup */ 333 cpufunc_null_fixup, /* prefetchabt_fixup */ 334 335 arm10_context_switch, /* context_switch */ 336 337 arm10_setup /* cpu setup */ 338 339}; 340#endif /* CPU_ARM10 */ 341 342#ifdef CPU_SA110 343struct cpu_functions sa110_cpufuncs = { 344 /* CPU functions */ 345 346 cpufunc_id, /* id */ 347 cpufunc_nullop, /* cpwait */ 348 349 /* MMU functions */ 350 351 cpufunc_control, /* control */ 352 cpufunc_domains, /* domain */ 353 sa1_setttb, /* setttb */ 354 cpufunc_faultstatus, /* faultstatus */ 355 cpufunc_faultaddress, /* faultaddress */ 356 357 /* TLB functions */ 358 359 armv4_tlb_flushID, /* tlb_flushID */ 360 sa1_tlb_flushID_SE, /* tlb_flushID_SE */ 361 armv4_tlb_flushI, /* tlb_flushI */ 362 (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ 363 armv4_tlb_flushD, /* tlb_flushD */ 364 armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 365 366 /* Cache operations */ 367 368 sa1_cache_syncI, /* icache_sync_all */ 369 sa1_cache_syncI_rng, /* icache_sync_range */ 370 371 sa1_cache_purgeD, /* dcache_wbinv_all */ 372 sa1_cache_purgeD_rng, /* dcache_wbinv_range */ 373/*XXX*/ sa1_cache_purgeD_rng, /* dcache_inv_range */ 374 sa1_cache_cleanD_rng, /* dcache_wb_range */ 375 376 sa1_cache_purgeID, /* idcache_wbinv_all */ 377 sa1_cache_purgeID_rng, /* idcache_wbinv_range */ 378 379 /* Other functions */ 380 381 cpufunc_nullop, /* flush_prefetchbuf */ 382 armv4_drain_writebuf, /* drain_writebuf */ 383 cpufunc_nullop, /* flush_brnchtgt_C */ 384 (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 385 386 (void *)cpufunc_nullop, /* sleep */ 387 388 /* Soft functions */ 389 390 cpufunc_null_fixup, /* dataabt_fixup */ 391 cpufunc_null_fixup, /* prefetchabt_fixup */ 392 393 sa110_context_switch, /* context_switch */ 394 395 sa110_setup /* cpu setup */ 396}; 397#endif /* CPU_SA110 */ 398 399#if defined(CPU_SA1100) || defined(CPU_SA1110) 400struct cpu_functions sa11x0_cpufuncs = { 401 /* CPU functions */ 402 403 cpufunc_id, /* id */ 404 cpufunc_nullop, /* cpwait */ 405 406 /* MMU functions */ 407 408 cpufunc_control, /* control */ 409 cpufunc_domains, /* domain */ 410 sa1_setttb, /* setttb */ 411 cpufunc_faultstatus, /* faultstatus */ 412 cpufunc_faultaddress, /* faultaddress */ 413 414 /* TLB functions */ 415 416 armv4_tlb_flushID, /* tlb_flushID */ 417 sa1_tlb_flushID_SE, /* tlb_flushID_SE */ 418 armv4_tlb_flushI, /* tlb_flushI */ 419 (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ 420 armv4_tlb_flushD, /* tlb_flushD */ 421 armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 422 423 /* Cache operations */ 424 425 sa1_cache_syncI, /* icache_sync_all */ 426 sa1_cache_syncI_rng, /* icache_sync_range */ 427 428 sa1_cache_purgeD, /* dcache_wbinv_all */ 429 sa1_cache_purgeD_rng, /* dcache_wbinv_range */ 430/*XXX*/ sa1_cache_purgeD_rng, /* dcache_inv_range */ 431 sa1_cache_cleanD_rng, /* dcache_wb_range */ 432 433 sa1_cache_purgeID, /* idcache_wbinv_all */ 434 sa1_cache_purgeID_rng, /* idcache_wbinv_range */ 435 436 /* Other functions */ 437 438 sa11x0_drain_readbuf, /* flush_prefetchbuf */ 439 armv4_drain_writebuf, /* drain_writebuf */ 440 cpufunc_nullop, /* flush_brnchtgt_C */ 441 (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 442 443 sa11x0_cpu_sleep, /* sleep */ 444 445 /* Soft functions */ 446 447 cpufunc_null_fixup, /* dataabt_fixup */ 448 cpufunc_null_fixup, /* prefetchabt_fixup */ 449 450 sa11x0_context_switch, /* context_switch */ 451 452 sa11x0_setup /* cpu setup */ 453}; 454#endif /* CPU_SA1100 || CPU_SA1110 */ 455 456#ifdef CPU_IXP12X0 457struct cpu_functions ixp12x0_cpufuncs = { 458 /* CPU functions */ 459 460 cpufunc_id, /* id */ 461 cpufunc_nullop, /* cpwait */ 462 463 /* MMU functions */ 464 465 cpufunc_control, /* control */ 466 cpufunc_domains, /* domain */ 467 sa1_setttb, /* setttb */ 468 cpufunc_faultstatus, /* faultstatus */ 469 cpufunc_faultaddress, /* faultaddress */ 470 471 /* TLB functions */ 472 473 armv4_tlb_flushID, /* tlb_flushID */ 474 sa1_tlb_flushID_SE, /* tlb_flushID_SE */ 475 armv4_tlb_flushI, /* tlb_flushI */ 476 (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ 477 armv4_tlb_flushD, /* tlb_flushD */ 478 armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 479 480 /* Cache operations */ 481 482 sa1_cache_syncI, /* icache_sync_all */ 483 sa1_cache_syncI_rng, /* icache_sync_range */ 484 485 sa1_cache_purgeD, /* dcache_wbinv_all */ 486 sa1_cache_purgeD_rng, /* dcache_wbinv_range */ 487/*XXX*/ sa1_cache_purgeD_rng, /* dcache_inv_range */ 488 sa1_cache_cleanD_rng, /* dcache_wb_range */ 489 490 sa1_cache_purgeID, /* idcache_wbinv_all */ 491 sa1_cache_purgeID_rng, /* idcache_wbinv_range */ 492 493 /* Other functions */ 494 495 ixp12x0_drain_readbuf, /* flush_prefetchbuf */ 496 armv4_drain_writebuf, /* drain_writebuf */ 497 cpufunc_nullop, /* flush_brnchtgt_C */ 498 (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 499 500 (void *)cpufunc_nullop, /* sleep */ 501 502 /* Soft functions */ 503 504 cpufunc_null_fixup, /* dataabt_fixup */ 505 cpufunc_null_fixup, /* prefetchabt_fixup */ 506 507 ixp12x0_context_switch, /* context_switch */ 508 509 ixp12x0_setup /* cpu setup */ 510}; 511#endif /* CPU_IXP12X0 */ 512 513#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ 514 defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) 515struct cpu_functions xscale_cpufuncs = { 516 /* CPU functions */ 517 518 cpufunc_id, /* id */ 519 xscale_cpwait, /* cpwait */ 520 521 /* MMU functions */ 522 523 xscale_control, /* control */ 524 cpufunc_domains, /* domain */ 525 xscale_setttb, /* setttb */ 526 cpufunc_faultstatus, /* faultstatus */ 527 cpufunc_faultaddress, /* faultaddress */ 528 529 /* TLB functions */ 530 531 armv4_tlb_flushID, /* tlb_flushID */ 532 xscale_tlb_flushID_SE, /* tlb_flushID_SE */ 533 armv4_tlb_flushI, /* tlb_flushI */ 534 (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ 535 armv4_tlb_flushD, /* tlb_flushD */ 536 armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 537 538 /* Cache operations */ 539 540 xscale_cache_syncI, /* icache_sync_all */ 541 xscale_cache_syncI_rng, /* icache_sync_range */ 542 543 xscale_cache_purgeD, /* dcache_wbinv_all */ 544 xscale_cache_purgeD_rng, /* dcache_wbinv_range */ 545 xscale_cache_flushD_rng, /* dcache_inv_range */ 546 xscale_cache_cleanD_rng, /* dcache_wb_range */ 547 548 xscale_cache_purgeID, /* idcache_wbinv_all */ 549 xscale_cache_purgeID_rng, /* idcache_wbinv_range */ 550 551 /* Other functions */ 552 553 cpufunc_nullop, /* flush_prefetchbuf */ 554 armv4_drain_writebuf, /* drain_writebuf */ 555 cpufunc_nullop, /* flush_brnchtgt_C */ 556 (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 557 558 xscale_cpu_sleep, /* sleep */ 559 560 /* Soft functions */ 561 562 cpufunc_null_fixup, /* dataabt_fixup */ 563 cpufunc_null_fixup, /* prefetchabt_fixup */ 564 565 xscale_context_switch, /* context_switch */ 566 567 xscale_setup /* cpu setup */ 568}; 569#endif 570/* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */ 571 572/* 573 * Global constants also used by locore.s 574 */ 575 576struct cpu_functions cpufuncs; 577u_int cputype; 578u_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore.s */ 579 580#if defined(CPU_ARM7TDMI) || defined(CPU_ARM8) || defined(CPU_ARM9) || \ 581 defined (CPU_ARM10) || \ 582 defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ 583 defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) 584static void get_cachetype_cp15(void); 585 586/* Additional cache information local to this file. Log2 of some of the 587 above numbers. */ 588static int arm_dcache_l2_nsets; 589static int arm_dcache_l2_assoc; 590static int arm_dcache_l2_linesize; 591 592static void 593get_cachetype_cp15() 594{ 595 u_int ctype, isize, dsize; 596 u_int multiplier; 597 598 __asm __volatile("mrc p15, 0, %0, c0, c0, 1" 599 : "=r" (ctype)); 600 601 /* 602 * ...and thus spake the ARM ARM: 603 * 604 * If an <opcode2> value corresponding to an unimplemented or 605 * reserved ID register is encountered, the System Control 606 * processor returns the value of the main ID register. 607 */ 608 if (ctype == cpufunc_id()) 609 goto out; 610 611 if ((ctype & CPU_CT_S) == 0) 612 arm_pcache_unified = 1; 613 614 /* 615 * If you want to know how this code works, go read the ARM ARM. 616 */ 617 618 arm_pcache_type = CPU_CT_CTYPE(ctype); 619 620 if (arm_pcache_unified == 0) { 621 isize = CPU_CT_ISIZE(ctype); 622 multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2; 623 arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3); 624 if (CPU_CT_xSIZE_ASSOC(isize) == 0) { 625 if (isize & CPU_CT_xSIZE_M) 626 arm_picache_line_size = 0; /* not present */ 627 else 628 arm_picache_ways = 1; 629 } else { 630 arm_picache_ways = multiplier << 631 (CPU_CT_xSIZE_ASSOC(isize) - 1); 632 } 633 arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8); 634 } 635 636 dsize = CPU_CT_DSIZE(ctype); 637 multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2; 638 arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3); 639 if (CPU_CT_xSIZE_ASSOC(dsize) == 0) { 640 if (dsize & CPU_CT_xSIZE_M) 641 arm_pdcache_line_size = 0; /* not present */ 642 else 643 arm_pdcache_ways = 1; 644 } else { 645 arm_pdcache_ways = multiplier << 646 (CPU_CT_xSIZE_ASSOC(dsize) - 1); 647 } 648 arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8); 649 650 arm_dcache_align = arm_pdcache_line_size; 651 652 arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2; 653 arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3; 654 arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) - 655 CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize); 656 657 out: 658 arm_dcache_align_mask = arm_dcache_align - 1; 659} 660#endif /* ARM7TDMI || ARM8 || ARM9 || XSCALE */ 661 662#if defined(CPU_SA110) || defined(CPU_SA1100) || defined(CPU_SA1110) || \ 663 defined(CPU_IXP12X0) 664/* Cache information for CPUs without cache type registers. */ 665struct cachetab { 666 u_int32_t ct_cpuid; 667 int ct_pcache_type; 668 int ct_pcache_unified; 669 int ct_pdcache_size; 670 int ct_pdcache_line_size; 671 int ct_pdcache_ways; 672 int ct_picache_size; 673 int ct_picache_line_size; 674 int ct_picache_ways; 675}; 676 677struct cachetab cachetab[] = { 678 /* cpuid, cache type, u, dsiz, ls, wy, isiz, ls, wy */ 679 /* XXX is this type right for SA-1? */ 680 { CPU_ID_SA110, CPU_CT_CTYPE_WB1, 0, 16384, 32, 32, 16384, 32, 32 }, 681 { CPU_ID_SA1100, CPU_CT_CTYPE_WB1, 0, 8192, 32, 32, 16384, 32, 32 }, 682 { CPU_ID_SA1110, CPU_CT_CTYPE_WB1, 0, 8192, 32, 32, 16384, 32, 32 }, 683 { CPU_ID_IXP1200, CPU_CT_CTYPE_WB1, 0, 16384, 32, 32, 16384, 32, 32 }, /* XXX */ 684 { 0, 0, 0, 0, 0, 0, 0, 0} 685}; 686 687static void get_cachetype_table(void); 688 689static void 690get_cachetype_table() 691{ 692 int i; 693 u_int32_t cpuid = cpufunc_id(); 694 695 for (i = 0; cachetab[i].ct_cpuid != 0; i++) { 696 if (cachetab[i].ct_cpuid == (cpuid & CPU_ID_CPU_MASK)) { 697 arm_pcache_type = cachetab[i].ct_pcache_type; 698 arm_pcache_unified = cachetab[i].ct_pcache_unified; 699 arm_pdcache_size = cachetab[i].ct_pdcache_size; 700 arm_pdcache_line_size = 701 cachetab[i].ct_pdcache_line_size; 702 arm_pdcache_ways = cachetab[i].ct_pdcache_ways; 703 arm_picache_size = cachetab[i].ct_picache_size; 704 arm_picache_line_size = 705 cachetab[i].ct_picache_line_size; 706 arm_picache_ways = cachetab[i].ct_picache_ways; 707 } 708 } 709 arm_dcache_align = arm_pdcache_line_size; 710 711 arm_dcache_align_mask = arm_dcache_align - 1; 712} 713 714#endif /* SA110 || SA1100 || SA1111 || IXP12X0 */ 715 716/* 717 * Cannot panic here as we may not have a console yet ... 718 */ 719 720int 721set_cpufuncs() 722{ 723 cputype = cpufunc_id(); 724 cputype &= CPU_ID_CPU_MASK; 725 726 /* 727 * NOTE: cpu_do_powersave defaults to off. If we encounter a 728 * CPU type where we want to use it by default, then we set it. 729 */ 730 731#ifdef CPU_ARM7TDMI 732 if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD && 733 CPU_ID_IS7(cputype) && 734 (cputype & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V4T) { 735 cpufuncs = arm7tdmi_cpufuncs; 736 cpu_reset_needs_v4_MMU_disable = 0; 737 get_cachetype_cp15(); 738 pmap_pte_init_generic(); 739 return 0; 740 } 741#endif 742#ifdef CPU_ARM8 743 if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD && 744 (cputype & 0x0000f000) == 0x00008000) { 745 cpufuncs = arm8_cpufuncs; 746 cpu_reset_needs_v4_MMU_disable = 0; /* XXX correct? */ 747 get_cachetype_cp15(); 748 pmap_pte_init_arm8(); 749 return 0; 750 } 751#endif /* CPU_ARM8 */ 752#ifdef CPU_ARM9 753 if (((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD || 754 (cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_TI) && 755 (cputype & 0x0000f000) == 0x00009000) { 756 cpufuncs = arm9_cpufuncs; 757 cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */ 758 get_cachetype_cp15(); 759 arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize; 760 arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize + 761 arm_dcache_l2_nsets)) - arm9_dcache_sets_inc; 762 arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc); 763 arm9_dcache_index_max = 0U - arm9_dcache_index_inc; 764#ifdef ARM9_CACHE_WRITE_THROUGH 765 pmap_pte_init_arm9(); 766#else 767 pmap_pte_init_generic(); 768#endif 769 return 0; 770 } 771#endif /* CPU_ARM9 */ 772#ifdef CPU_ARM10 773 if (/* cputype == CPU_ID_ARM1020T || */ 774 cputype == CPU_ID_ARM1020E) { 775 /* 776 * Select write-through cacheing (this isn't really an 777 * option on ARM1020T). 778 */ 779 cpufuncs = arm10_cpufuncs; 780 cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */ 781 get_cachetype_cp15(); 782 arm10_dcache_sets_inc = 1U << arm_dcache_l2_linesize; 783 arm10_dcache_sets_max = 784 (1U << (arm_dcache_l2_linesize + arm_dcache_l2_nsets)) - 785 arm10_dcache_sets_inc; 786 arm10_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc); 787 arm10_dcache_index_max = 0U - arm10_dcache_index_inc; 788 pmap_pte_init_generic(); 789 return 0; 790 } 791#endif /* CPU_ARM10 */ 792#ifdef CPU_SA110 793 if (cputype == CPU_ID_SA110) { 794 cpufuncs = sa110_cpufuncs; 795 cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */ 796 get_cachetype_table(); 797 pmap_pte_init_sa1(); 798 return 0; 799 } 800#endif /* CPU_SA110 */ 801#ifdef CPU_SA1100 802 if (cputype == CPU_ID_SA1100) { 803 cpufuncs = sa11x0_cpufuncs; 804 cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */ 805 get_cachetype_table(); 806 pmap_pte_init_sa1(); 807 /* Use powersave on this CPU. */ 808 cpu_do_powersave = 1; 809 810 return 0; 811 } 812#endif /* CPU_SA1100 */ 813#ifdef CPU_SA1110 814 if (cputype == CPU_ID_SA1110) { 815 cpufuncs = sa11x0_cpufuncs; 816 cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */ 817 get_cachetype_table(); 818 pmap_pte_init_sa1(); 819 /* Use powersave on this CPU. */ 820 cpu_do_powersave = 1; 821 822 return 0; 823 } 824#endif /* CPU_SA1110 */ 825#ifdef CPU_IXP12X0 826 if (cputype == CPU_ID_IXP1200) { 827 cpufuncs = ixp12x0_cpufuncs; 828 cpu_reset_needs_v4_MMU_disable = 1; 829 get_cachetype_table(); 830 pmap_pte_init_sa1(); 831 return 0; 832 } 833#endif /* CPU_IXP12X0 */ 834#ifdef CPU_XSCALE_80200 835 if (cputype == CPU_ID_80200) { 836 int rev = cpufunc_id() & CPU_ID_REVISION_MASK; 837 838 i80200_icu_init(); 839 840 /* 841 * Reset the Performance Monitoring Unit to a 842 * pristine state: 843 * - CCNT, PMN0, PMN1 reset to 0 844 * - overflow indications cleared 845 * - all counters disabled 846 */ 847 __asm __volatile("mcr p14, 0, %0, c0, c0, 0" 848 : 849 : "r" (PMNC_P|PMNC_C|PMNC_PMN0_IF|PMNC_PMN1_IF| 850 PMNC_CC_IF)); 851 852#if defined(XSCALE_CCLKCFG) 853 /* 854 * Crank CCLKCFG to maximum legal value. 855 */ 856 __asm __volatile ("mcr p14, 0, %0, c6, c0, 0" 857 : 858 : "r" (XSCALE_CCLKCFG)); 859#endif 860 861 /* 862 * XXX Disable ECC in the Bus Controller Unit; we 863 * don't really support it, yet. Clear any pending 864 * error indications. 865 */ 866 __asm __volatile("mcr p13, 0, %0, c0, c1, 0" 867 : 868 : "r" (BCUCTL_E0|BCUCTL_E1|BCUCTL_EV)); 869 870 cpufuncs = xscale_cpufuncs; 871#if defined(PERFCTRS) 872 xscale_pmu_init(); 873#endif 874 875 /* 876 * i80200 errata: Step-A0 and A1 have a bug where 877 * D$ dirty bits are not cleared on "invalidate by 878 * address". 879 * 880 * Workaround: Clean cache line before invalidating. 881 */ 882 if (rev == 0 || rev == 1) 883 cpufuncs.cf_dcache_inv_range = xscale_cache_purgeD_rng; 884 885 cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 886 get_cachetype_cp15(); 887 pmap_pte_init_xscale(); 888 return 0; 889 } 890#endif /* CPU_XSCALE_80200 */ 891#ifdef CPU_XSCALE_80321 892 if (cputype == CPU_ID_80321_400 || cputype == CPU_ID_80321_600 || 893 cputype == CPU_ID_80321_400_B0 || cputype == CPU_ID_80321_600_B0) { 894 895 /* 896 * Reset the Performance Monitoring Unit to a 897 * pristine state: 898 * - CCNT, PMN0, PMN1 reset to 0 899 * - overflow indications cleared 900 * - all counters disabled 901 */ 902 __asm __volatile("mcr p14, 0, %0, c0, c0, 0" 903 : 904 : "r" (PMNC_P|PMNC_C|PMNC_PMN0_IF|PMNC_PMN1_IF| 905 PMNC_CC_IF)); 906 907 cpufuncs = xscale_cpufuncs; 908#if defined(PERFCTRS) 909 xscale_pmu_init(); 910#endif 911 912 cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 913 get_cachetype_cp15(); 914 pmap_pte_init_xscale(); 915 return 0; 916 } 917#endif /* CPU_XSCALE_80321 */ 918#ifdef CPU_XSCALE_PXA2X0 919 /* ignore core revision to test PXA2xx CPUs */ 920 if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA250 || 921 (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA210) { 922 923 cpufuncs = xscale_cpufuncs; 924#if defined(PERFCTRS) 925 xscale_pmu_init(); 926#endif 927 928 cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 929 get_cachetype_cp15(); 930 pmap_pte_init_xscale(); 931 932 /* Use powersave on this CPU. */ 933 cpu_do_powersave = 1; 934 935 return 0; 936 } 937#endif /* CPU_XSCALE_PXA2X0 */ 938#ifdef CPU_XSCALE_IXP425 939 if (cputype == CPU_ID_IXP425_533 || cputype == CPU_ID_IXP425_400 || 940 cputype == CPU_ID_IXP425_266) { 941 ixp425_icu_init(); 942 943 cpufuncs = xscale_cpufuncs; 944#if defined(PERFCTRS) 945 xscale_pmu_init(); 946#endif 947 948 cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 949 get_cachetype_cp15(); 950 pmap_pte_init_xscale(); 951 952 return 0; 953 } 954#endif /* CPU_XSCALE_IXP425 */ 955 /* 956 * Bzzzz. And the answer was ... 957 */ 958 panic("No support for this CPU type (%08x) in kernel", cputype); 959 return(ARCHITECTURE_NOT_PRESENT); 960} 961 962/* 963 * Fixup routines for data and prefetch aborts. 964 * 965 * Several compile time symbols are used 966 * 967 * DEBUG_FAULT_CORRECTION - Print debugging information during the 968 * correction of registers after a fault. 969 * ARM6_LATE_ABORT - ARM6 supports both early and late aborts 970 * when defined should use late aborts 971 */ 972 973 974/* 975 * Null abort fixup routine. 976 * For use when no fixup is required. 977 */ 978int 979cpufunc_null_fixup(arg) 980 void *arg; 981{ 982 return(ABORT_FIXUP_OK); 983} 984 985 986#if defined(CPU_ARM7TDMI) 987 988#ifdef DEBUG_FAULT_CORRECTION 989#define DFC_PRINTF(x) printf x 990#define DFC_DISASSEMBLE(x) disassemble(x) 991#else 992#define DFC_PRINTF(x) /* nothing */ 993#define DFC_DISASSEMBLE(x) /* nothing */ 994#endif 995 996/* 997 * "Early" data abort fixup. 998 * 999 * For ARM2, ARM2as, ARM3 and ARM6 (in early-abort mode). Also used 1000 * indirectly by ARM6 (in late-abort mode) and ARM7[TDMI]. 1001 * 1002 * In early aborts, we may have to fix up LDM, STM, LDC and STC. 1003 */ 1004int 1005early_abort_fixup(arg) 1006 void *arg; 1007{ 1008 trapframe_t *frame = arg; 1009 u_int fault_pc; 1010 u_int fault_instruction; 1011 int saved_lr = 0; 1012 1013 if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { 1014 1015 /* Ok an abort in SVC mode */ 1016 1017 /* 1018 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage 1019 * as the fault happened in svc mode but we need it in the 1020 * usr slot so we can treat the registers as an array of ints 1021 * during fixing. 1022 * NOTE: This PC is in the position but writeback is not 1023 * allowed on r15. 1024 * Doing it like this is more efficient than trapping this 1025 * case in all possible locations in the following fixup code. 1026 */ 1027 1028 saved_lr = frame->tf_usr_lr; 1029 frame->tf_usr_lr = frame->tf_svc_lr; 1030 1031 /* 1032 * Note the trapframe does not have the SVC r13 so a fault 1033 * from an instruction with writeback to r13 in SVC mode is 1034 * not allowed. This should not happen as the kstack is 1035 * always valid. 1036 */ 1037 } 1038 1039 /* Get fault address and status from the CPU */ 1040 1041 fault_pc = frame->tf_pc; 1042 fault_instruction = *((volatile unsigned int *)fault_pc); 1043 1044 /* Decode the fault instruction and fix the registers as needed */ 1045 1046 if ((fault_instruction & 0x0e000000) == 0x08000000) { 1047 int base; 1048 int loop; 1049 int count; 1050 int *registers = &frame->tf_r0; 1051 1052 DFC_PRINTF(("LDM/STM\n")); 1053 DFC_DISASSEMBLE(fault_pc); 1054 if (fault_instruction & (1 << 21)) { 1055 DFC_PRINTF(("This instruction must be corrected\n")); 1056 base = (fault_instruction >> 16) & 0x0f; 1057 if (base == 15) 1058 return ABORT_FIXUP_FAILED; 1059 /* Count registers transferred */ 1060 count = 0; 1061 for (loop = 0; loop < 16; ++loop) { 1062 if (fault_instruction & (1<<loop)) 1063 ++count; 1064 } 1065 DFC_PRINTF(("%d registers used\n", count)); 1066 DFC_PRINTF(("Corrected r%d by %d bytes ", 1067 base, count * 4)); 1068 if (fault_instruction & (1 << 23)) { 1069 DFC_PRINTF(("down\n")); 1070 registers[base] -= count * 4; 1071 } else { 1072 DFC_PRINTF(("up\n")); 1073 registers[base] += count * 4; 1074 } 1075 } 1076 } else if ((fault_instruction & 0x0e000000) == 0x0c000000) { 1077 int base; 1078 int offset; 1079 int *registers = &frame->tf_r0; 1080 1081 /* REGISTER CORRECTION IS REQUIRED FOR THESE INSTRUCTIONS */ 1082 1083 DFC_DISASSEMBLE(fault_pc); 1084 1085 /* Only need to fix registers if write back is turned on */ 1086 1087 if ((fault_instruction & (1 << 21)) != 0) { 1088 base = (fault_instruction >> 16) & 0x0f; 1089 if (base == 13 && 1090 (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) 1091 return ABORT_FIXUP_FAILED; 1092 if (base == 15) 1093 return ABORT_FIXUP_FAILED; 1094 1095 offset = (fault_instruction & 0xff) << 2; 1096 DFC_PRINTF(("r%d=%08x\n", base, registers[base])); 1097 if ((fault_instruction & (1 << 23)) != 0) 1098 offset = -offset; 1099 registers[base] += offset; 1100 DFC_PRINTF(("r%d=%08x\n", base, registers[base])); 1101 } 1102 } else if ((fault_instruction & 0x0e000000) == 0x0c000000) 1103 return ABORT_FIXUP_FAILED; 1104 1105 if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { 1106 1107 /* Ok an abort in SVC mode */ 1108 1109 /* 1110 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage 1111 * as the fault happened in svc mode but we need it in the 1112 * usr slot so we can treat the registers as an array of ints 1113 * during fixing. 1114 * NOTE: This PC is in the position but writeback is not 1115 * allowed on r15. 1116 * Doing it like this is more efficient than trapping this 1117 * case in all possible locations in the prior fixup code. 1118 */ 1119 1120 frame->tf_svc_lr = frame->tf_usr_lr; 1121 frame->tf_usr_lr = saved_lr; 1122 1123 /* 1124 * Note the trapframe does not have the SVC r13 so a fault 1125 * from an instruction with writeback to r13 in SVC mode is 1126 * not allowed. This should not happen as the kstack is 1127 * always valid. 1128 */ 1129 } 1130 1131 return(ABORT_FIXUP_OK); 1132} 1133#endif /* CPU_ARM2/250/3/6/7 */ 1134 1135 1136#if defined(CPU_ARM7TDMI) 1137/* 1138 * "Late" (base updated) data abort fixup 1139 * 1140 * For ARM6 (in late-abort mode) and ARM7. 1141 * 1142 * In this model, all data-transfer instructions need fixing up. We defer 1143 * LDM, STM, LDC and STC fixup to the early-abort handler. 1144 */ 1145int 1146late_abort_fixup(arg) 1147 void *arg; 1148{ 1149 trapframe_t *frame = arg; 1150 u_int fault_pc; 1151 u_int fault_instruction; 1152 int saved_lr = 0; 1153 1154 if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { 1155 1156 /* Ok an abort in SVC mode */ 1157 1158 /* 1159 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage 1160 * as the fault happened in svc mode but we need it in the 1161 * usr slot so we can treat the registers as an array of ints 1162 * during fixing. 1163 * NOTE: This PC is in the position but writeback is not 1164 * allowed on r15. 1165 * Doing it like this is more efficient than trapping this 1166 * case in all possible locations in the following fixup code. 1167 */ 1168 1169 saved_lr = frame->tf_usr_lr; 1170 frame->tf_usr_lr = frame->tf_svc_lr; 1171 1172 /* 1173 * Note the trapframe does not have the SVC r13 so a fault 1174 * from an instruction with writeback to r13 in SVC mode is 1175 * not allowed. This should not happen as the kstack is 1176 * always valid. 1177 */ 1178 } 1179 1180 /* Get fault address and status from the CPU */ 1181 1182 fault_pc = frame->tf_pc; 1183 fault_instruction = *((volatile unsigned int *)fault_pc); 1184 1185 /* Decode the fault instruction and fix the registers as needed */ 1186 1187 /* Was is a swap instruction ? */ 1188 1189 if ((fault_instruction & 0x0fb00ff0) == 0x01000090) { 1190 DFC_DISASSEMBLE(fault_pc); 1191 } else if ((fault_instruction & 0x0c000000) == 0x04000000) { 1192 1193 /* Was is a ldr/str instruction */ 1194 /* This is for late abort only */ 1195 1196 int base; 1197 int offset; 1198 int *registers = &frame->tf_r0; 1199 1200 DFC_DISASSEMBLE(fault_pc); 1201 1202 /* This is for late abort only */ 1203 1204 if ((fault_instruction & (1 << 24)) == 0 1205 || (fault_instruction & (1 << 21)) != 0) { 1206 /* postindexed ldr/str with no writeback */ 1207 1208 base = (fault_instruction >> 16) & 0x0f; 1209 if (base == 13 && 1210 (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) 1211 return ABORT_FIXUP_FAILED; 1212 if (base == 15) 1213 return ABORT_FIXUP_FAILED; 1214 DFC_PRINTF(("late abt fix: r%d=%08x : ", 1215 base, registers[base])); 1216 if ((fault_instruction & (1 << 25)) == 0) { 1217 /* Immediate offset - easy */ 1218 1219 offset = fault_instruction & 0xfff; 1220 if ((fault_instruction & (1 << 23))) 1221 offset = -offset; 1222 registers[base] += offset; 1223 DFC_PRINTF(("imm=%08x ", offset)); 1224 } else { 1225 /* offset is a shifted register */ 1226 int shift; 1227 1228 offset = fault_instruction & 0x0f; 1229 if (offset == base) 1230 return ABORT_FIXUP_FAILED; 1231 1232 /* 1233 * Register offset - hard we have to 1234 * cope with shifts ! 1235 */ 1236 offset = registers[offset]; 1237 1238 if ((fault_instruction & (1 << 4)) == 0) 1239 /* shift with amount */ 1240 shift = (fault_instruction >> 7) & 0x1f; 1241 else { 1242 /* shift with register */ 1243 if ((fault_instruction & (1 << 7)) != 0) 1244 /* undefined for now so bail out */ 1245 return ABORT_FIXUP_FAILED; 1246 shift = ((fault_instruction >> 8) & 0xf); 1247 if (base == shift) 1248 return ABORT_FIXUP_FAILED; 1249 DFC_PRINTF(("shift reg=%d ", shift)); 1250 shift = registers[shift]; 1251 } 1252 DFC_PRINTF(("shift=%08x ", shift)); 1253 switch (((fault_instruction >> 5) & 0x3)) { 1254 case 0 : /* Logical left */ 1255 offset = (int)(((u_int)offset) << shift); 1256 break; 1257 case 1 : /* Logical Right */ 1258 if (shift == 0) shift = 32; 1259 offset = (int)(((u_int)offset) >> shift); 1260 break; 1261 case 2 : /* Arithmetic Right */ 1262 if (shift == 0) shift = 32; 1263 offset = (int)(((int)offset) >> shift); 1264 break; 1265 case 3 : /* Rotate right (rol or rxx) */ 1266 return ABORT_FIXUP_FAILED; 1267 break; 1268 } 1269 1270 DFC_PRINTF(("abt: fixed LDR/STR with " 1271 "register offset\n")); 1272 if ((fault_instruction & (1 << 23))) 1273 offset = -offset; 1274 DFC_PRINTF(("offset=%08x ", offset)); 1275 registers[base] += offset; 1276 } 1277 DFC_PRINTF(("r%d=%08x\n", base, registers[base])); 1278 } 1279 } 1280 1281 if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { 1282 1283 /* Ok an abort in SVC mode */ 1284 1285 /* 1286 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage 1287 * as the fault happened in svc mode but we need it in the 1288 * usr slot so we can treat the registers as an array of ints 1289 * during fixing. 1290 * NOTE: This PC is in the position but writeback is not 1291 * allowed on r15. 1292 * Doing it like this is more efficient than trapping this 1293 * case in all possible locations in the prior fixup code. 1294 */ 1295 1296 frame->tf_svc_lr = frame->tf_usr_lr; 1297 frame->tf_usr_lr = saved_lr; 1298 1299 /* 1300 * Note the trapframe does not have the SVC r13 so a fault 1301 * from an instruction with writeback to r13 in SVC mode is 1302 * not allowed. This should not happen as the kstack is 1303 * always valid. 1304 */ 1305 } 1306 1307 /* 1308 * Now let the early-abort fixup routine have a go, in case it 1309 * was an LDM, STM, LDC or STC that faulted. 1310 */ 1311 1312 return early_abort_fixup(arg); 1313} 1314#endif /* CPU_ARM7TDMI */ 1315 1316/* 1317 * CPU Setup code 1318 */ 1319 1320#if defined(CPU_ARM7TDMI) || defined(CPU_ARM8) || defined (CPU_ARM9) || \ 1321 defined(CPU_SA110) || defined(CPU_SA1100) || defined(CPU_SA1110) || \ 1322 defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ 1323 defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) 1324 1325#define IGN 0 1326#define OR 1 1327#define BIC 2 1328 1329struct cpu_option { 1330 char *co_name; 1331 int co_falseop; 1332 int co_trueop; 1333 int co_value; 1334}; 1335 1336static u_int parse_cpu_options(char *, struct cpu_option *, u_int); 1337 1338static u_int 1339parse_cpu_options(args, optlist, cpuctrl) 1340 char *args; 1341 struct cpu_option *optlist; 1342 u_int cpuctrl; 1343{ 1344 int integer; 1345 1346 if (args == NULL) 1347 return(cpuctrl); 1348 1349 while (optlist->co_name) { 1350 if (get_bootconf_option(args, optlist->co_name, 1351 BOOTOPT_TYPE_BOOLEAN, &integer)) { 1352 if (integer) { 1353 if (optlist->co_trueop == OR) 1354 cpuctrl |= optlist->co_value; 1355 else if (optlist->co_trueop == BIC) 1356 cpuctrl &= ~optlist->co_value; 1357 } else { 1358 if (optlist->co_falseop == OR) 1359 cpuctrl |= optlist->co_value; 1360 else if (optlist->co_falseop == BIC) 1361 cpuctrl &= ~optlist->co_value; 1362 } 1363 } 1364 ++optlist; 1365 } 1366 return(cpuctrl); 1367} 1368#endif /* CPU_ARM7TDMI || CPU_ARM8 || CPU_SA110 */ 1369 1370#if defined(CPU_ARM7TDMI) || defined(CPU_ARM8) 1371struct cpu_option arm678_options[] = { 1372#ifdef COMPAT_12 1373 { "nocache", IGN, BIC, CPU_CONTROL_IDC_ENABLE }, 1374 { "nowritebuf", IGN, BIC, CPU_CONTROL_WBUF_ENABLE }, 1375#endif /* COMPAT_12 */ 1376 { "cpu.cache", BIC, OR, CPU_CONTROL_IDC_ENABLE }, 1377 { "cpu.nocache", OR, BIC, CPU_CONTROL_IDC_ENABLE }, 1378 { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1379 { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1380 { NULL, IGN, IGN, 0 } 1381}; 1382 1383#endif /* CPU_ARM6 || CPU_ARM7 || CPU_ARM7TDMI || CPU_ARM8 */ 1384 1385#ifdef CPU_ARM7TDMI 1386struct cpu_option arm7tdmi_options[] = { 1387 { "arm7.cache", BIC, OR, CPU_CONTROL_IDC_ENABLE }, 1388 { "arm7.nocache", OR, BIC, CPU_CONTROL_IDC_ENABLE }, 1389 { "arm7.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1390 { "arm7.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1391#ifdef COMPAT_12 1392 { "fpaclk2", BIC, OR, CPU_CONTROL_CPCLK }, 1393#endif /* COMPAT_12 */ 1394 { "arm700.fpaclk", BIC, OR, CPU_CONTROL_CPCLK }, 1395 { NULL, IGN, IGN, 0 } 1396}; 1397 1398void 1399arm7tdmi_setup(args) 1400 char *args; 1401{ 1402 int cpuctrl; 1403 1404 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1405 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1406 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE; 1407 1408 cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl); 1409 cpuctrl = parse_cpu_options(args, arm7tdmi_options, cpuctrl); 1410 1411#ifdef __ARMEB__ 1412 cpuctrl |= CPU_CONTROL_BEND_ENABLE; 1413#endif 1414 1415 /* Clear out the cache */ 1416 cpu_idcache_wbinv_all(); 1417 1418 /* Set the control register */ 1419 ctrl = cpuctrl; 1420 cpu_control(0xffffffff, cpuctrl); 1421} 1422#endif /* CPU_ARM7TDMI */ 1423 1424#ifdef CPU_ARM8 1425struct cpu_option arm8_options[] = { 1426 { "arm8.cache", BIC, OR, CPU_CONTROL_IDC_ENABLE }, 1427 { "arm8.nocache", OR, BIC, CPU_CONTROL_IDC_ENABLE }, 1428 { "arm8.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1429 { "arm8.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1430#ifdef COMPAT_12 1431 { "branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, 1432#endif /* COMPAT_12 */ 1433 { "cpu.branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, 1434 { "arm8.branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, 1435 { NULL, IGN, IGN, 0 } 1436}; 1437 1438void 1439arm8_setup(args) 1440 char *args; 1441{ 1442 int integer; 1443 int cpuctrl, cpuctrlmask; 1444 int clocktest; 1445 int setclock = 0; 1446 1447 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1448 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1449 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE; 1450 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1451 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1452 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE 1453 | CPU_CONTROL_BPRD_ENABLE | CPU_CONTROL_ROM_ENABLE 1454 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE; 1455 1456#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 1457 cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 1458#endif 1459 1460 cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl); 1461 cpuctrl = parse_cpu_options(args, arm8_options, cpuctrl); 1462 1463#ifdef __ARMEB__ 1464 cpuctrl |= CPU_CONTROL_BEND_ENABLE; 1465#endif 1466 1467 /* Get clock configuration */ 1468 clocktest = arm8_clock_config(0, 0) & 0x0f; 1469 1470 /* Special ARM8 clock and test configuration */ 1471 if (get_bootconf_option(args, "arm8.clock.reset", BOOTOPT_TYPE_BOOLEAN, &integer)) { 1472 clocktest = 0; 1473 setclock = 1; 1474 } 1475 if (get_bootconf_option(args, "arm8.clock.dynamic", BOOTOPT_TYPE_BOOLEAN, &integer)) { 1476 if (integer) 1477 clocktest |= 0x01; 1478 else 1479 clocktest &= ~(0x01); 1480 setclock = 1; 1481 } 1482 if (get_bootconf_option(args, "arm8.clock.sync", BOOTOPT_TYPE_BOOLEAN, &integer)) { 1483 if (integer) 1484 clocktest |= 0x02; 1485 else 1486 clocktest &= ~(0x02); 1487 setclock = 1; 1488 } 1489 if (get_bootconf_option(args, "arm8.clock.fast", BOOTOPT_TYPE_BININT, &integer)) { 1490 clocktest = (clocktest & ~0xc0) | (integer & 3) << 2; 1491 setclock = 1; 1492 } 1493 if (get_bootconf_option(args, "arm8.test", BOOTOPT_TYPE_BININT, &integer)) { 1494 clocktest |= (integer & 7) << 5; 1495 setclock = 1; 1496 } 1497 1498 /* Clear out the cache */ 1499 cpu_idcache_wbinv_all(); 1500 1501 /* Set the control register */ 1502 ctrl = cpuctrl; 1503 cpu_control(0xffffffff, cpuctrl); 1504 1505 /* Set the clock/test register */ 1506 if (setclock) 1507 arm8_clock_config(0x7f, clocktest); 1508} 1509#endif /* CPU_ARM8 */ 1510 1511#ifdef CPU_ARM9 1512struct cpu_option arm9_options[] = { 1513 { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1514 { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1515 { "arm9.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1516 { "arm9.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, 1517 { "arm9.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, 1518 { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1519 { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1520 { "arm9.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1521 { NULL, IGN, IGN, 0 } 1522}; 1523 1524void 1525arm9_setup(args) 1526 char *args; 1527{ 1528 int cpuctrl, cpuctrlmask; 1529 1530 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1531 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1532 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1533 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE; 1534 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1535 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1536 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1537 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 1538 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 1539 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_VECRELOC 1540 | CPU_CONTROL_ROUNDROBIN; 1541 1542#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 1543 cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 1544#endif 1545 1546 cpuctrl = parse_cpu_options(args, arm9_options, cpuctrl); 1547 1548#ifdef __ARMEB__ 1549 cpuctrl |= CPU_CONTROL_BEND_ENABLE; 1550#endif 1551 if (vector_page == ARM_VECTORS_HIGH) 1552 cpuctrl |= CPU_CONTROL_VECRELOC; 1553 1554 /* Clear out the cache */ 1555 cpu_idcache_wbinv_all(); 1556 1557 /* Set the control register */ 1558 cpu_control(cpuctrlmask, cpuctrl); 1559 ctrl = cpuctrl; 1560 1561} 1562#endif /* CPU_ARM9 */ 1563 1564#ifdef CPU_ARM10 1565struct cpu_option arm10_options[] = { 1566 { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1567 { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1568 { "arm10.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1569 { "arm10.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, 1570 { "arm10.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, 1571 { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1572 { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1573 { "arm10.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1574 { NULL, IGN, IGN, 0 } 1575}; 1576 1577void 1578arm10_setup(args) 1579 char *args; 1580{ 1581 int cpuctrl, cpuctrlmask; 1582 1583 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE 1584 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1585 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE; 1586 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE 1587 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1588 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 1589 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 1590 | CPU_CONTROL_BPRD_ENABLE 1591 | CPU_CONTROL_ROUNDROBIN | CPU_CONTROL_CPCLK; 1592 1593#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 1594 cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 1595#endif 1596 1597 cpuctrl = parse_cpu_options(args, arm10_options, cpuctrl); 1598 1599#ifdef __ARMEB__ 1600 cpuctrl |= CPU_CONTROL_BEND_ENABLE; 1601#endif 1602 1603 /* Clear out the cache */ 1604 cpu_idcache_wbinv_all(); 1605 1606 /* Now really make sure they are clean. */ 1607 asm volatile ("mcr\tp15, 0, r0, c7, c7, 0" : : ); 1608 1609 /* Set the control register */ 1610 ctrl = cpuctrl; 1611 cpu_control(0xffffffff, cpuctrl); 1612 1613 /* And again. */ 1614 cpu_idcache_wbinv_all(); 1615} 1616#endif /* CPU_ARM10 */ 1617 1618#ifdef CPU_SA110 1619struct cpu_option sa110_options[] = { 1620#ifdef COMPAT_12 1621 { "nocache", IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1622 { "nowritebuf", IGN, BIC, CPU_CONTROL_WBUF_ENABLE }, 1623#endif /* COMPAT_12 */ 1624 { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1625 { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1626 { "sa110.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1627 { "sa110.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, 1628 { "sa110.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, 1629 { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1630 { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1631 { "sa110.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1632 { NULL, IGN, IGN, 0 } 1633}; 1634 1635void 1636sa110_setup(args) 1637 char *args; 1638{ 1639 int cpuctrl, cpuctrlmask; 1640 1641 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1642 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1643 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1644 | CPU_CONTROL_WBUF_ENABLE; 1645 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1646 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1647 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1648 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 1649 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 1650 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE 1651 | CPU_CONTROL_CPCLK; 1652 1653#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 1654 cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 1655#endif 1656 1657 cpuctrl = parse_cpu_options(args, sa110_options, cpuctrl); 1658 1659#ifdef __ARMEB__ 1660 cpuctrl |= CPU_CONTROL_BEND_ENABLE; 1661#endif 1662 1663 /* Clear out the cache */ 1664 cpu_idcache_wbinv_all(); 1665 1666 /* Set the control register */ 1667 ctrl = cpuctrl; 1668/* cpu_control(cpuctrlmask, cpuctrl);*/ 1669 cpu_control(0xffffffff, cpuctrl); 1670 1671 /* 1672 * enable clockswitching, note that this doesn't read or write to r0, 1673 * r0 is just to make it valid asm 1674 */ 1675 __asm ("mcr 15, 0, r0, c15, c1, 2"); 1676} 1677#endif /* CPU_SA110 */ 1678 1679#if defined(CPU_SA1100) || defined(CPU_SA1110) 1680struct cpu_option sa11x0_options[] = { 1681#ifdef COMPAT_12 1682 { "nocache", IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1683 { "nowritebuf", IGN, BIC, CPU_CONTROL_WBUF_ENABLE }, 1684#endif /* COMPAT_12 */ 1685 { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1686 { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1687 { "sa11x0.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1688 { "sa11x0.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, 1689 { "sa11x0.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, 1690 { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1691 { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1692 { "sa11x0.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1693 { NULL, IGN, IGN, 0 } 1694}; 1695 1696void 1697sa11x0_setup(args) 1698 char *args; 1699{ 1700 int cpuctrl, cpuctrlmask; 1701 1702 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1703 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1704 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1705 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE; 1706 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1707 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1708 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1709 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 1710 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 1711 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE 1712 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC; 1713 1714#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 1715 cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 1716#endif 1717 1718 1719 cpuctrl = parse_cpu_options(args, sa11x0_options, cpuctrl); 1720 1721#ifdef __ARMEB__ 1722 cpuctrl |= CPU_CONTROL_BEND_ENABLE; 1723#endif 1724 1725 if (vector_page == ARM_VECTORS_HIGH) 1726 cpuctrl |= CPU_CONTROL_VECRELOC; 1727 /* Clear out the cache */ 1728 cpu_idcache_wbinv_all(); 1729 /* Set the control register */ 1730 ctrl = cpuctrl; 1731 cpu_control(0xffffffff, cpuctrl); 1732} 1733#endif /* CPU_SA1100 || CPU_SA1110 */ 1734 1735#if defined(CPU_IXP12X0) 1736struct cpu_option ixp12x0_options[] = { 1737 { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1738 { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1739 { "ixp12x0.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1740 { "ixp12x0.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, 1741 { "ixp12x0.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, 1742 { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1743 { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1744 { "ixp12x0.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1745 { NULL, IGN, IGN, 0 } 1746}; 1747 1748void 1749ixp12x0_setup(args) 1750 char *args; 1751{ 1752 int cpuctrl, cpuctrlmask; 1753 1754 1755 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE 1756 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_SYST_ENABLE 1757 | CPU_CONTROL_IC_ENABLE; 1758 1759 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_AFLT_ENABLE 1760 | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE 1761 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_SYST_ENABLE 1762 | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_IC_ENABLE 1763 | CPU_CONTROL_VECRELOC; 1764 1765#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 1766 cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 1767#endif 1768 1769 cpuctrl = parse_cpu_options(args, ixp12x0_options, cpuctrl); 1770 1771#ifdef __ARMEB__ 1772 cpuctrl |= CPU_CONTROL_BEND_ENABLE; 1773#endif 1774 1775 if (vector_page == ARM_VECTORS_HIGH) 1776 cpuctrl |= CPU_CONTROL_VECRELOC; 1777 1778 /* Clear out the cache */ 1779 cpu_idcache_wbinv_all(); 1780 1781 /* Set the control register */ 1782 ctrl = cpuctrl; 1783 /* cpu_control(0xffffffff, cpuctrl); */ 1784 cpu_control(cpuctrlmask, cpuctrl); 1785} 1786#endif /* CPU_IXP12X0 */ 1787 1788#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ 1789 defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) 1790struct cpu_option xscale_options[] = { 1791#ifdef COMPAT_12 1792 { "branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, 1793 { "nocache", IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1794#endif /* COMPAT_12 */ 1795 { "cpu.branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, 1796 { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1797 { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1798 { "xscale.branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, 1799 { "xscale.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1800 { "xscale.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, 1801 { "xscale.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, 1802 { NULL, IGN, IGN, 0 } 1803}; 1804 1805void 1806xscale_setup(args) 1807 char *args; 1808{ 1809 uint32_t auxctl; 1810 int cpuctrl, cpuctrlmask; 1811 1812 /* 1813 * The XScale Write Buffer is always enabled. Our option 1814 * is to enable/disable coalescing. Note that bits 6:3 1815 * must always be enabled. 1816 */ 1817 1818 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1819 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1820 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1821 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE 1822 | CPU_CONTROL_BPRD_ENABLE; 1823 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1824 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1825 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1826 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 1827 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 1828 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE 1829 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC; 1830 1831#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 1832 cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 1833#endif 1834 1835 cpuctrl = parse_cpu_options(args, xscale_options, cpuctrl); 1836 1837#ifdef __ARMEB__ 1838 cpuctrl |= CPU_CONTROL_BEND_ENABLE; 1839#endif 1840 1841 if (vector_page == ARM_VECTORS_HIGH) 1842 cpuctrl |= CPU_CONTROL_VECRELOC; 1843 1844 /* Clear out the cache */ 1845 cpu_idcache_wbinv_all(); 1846 1847 /* 1848 * Set the control register. Note that bits 6:3 must always 1849 * be set to 1. 1850 */ 1851 ctrl = cpuctrl; 1852/* cpu_control(cpuctrlmask, cpuctrl);*/ 1853 cpu_control(0xffffffff, cpuctrl); 1854 1855 /* Make sure write coalescing is turned on */ 1856 __asm __volatile("mrc p15, 0, %0, c1, c0, 1" 1857 : "=r" (auxctl)); 1858#ifdef XSCALE_NO_COALESCE_WRITES 1859 auxctl |= XSCALE_AUXCTL_K; 1860#else 1861 auxctl &= ~XSCALE_AUXCTL_K; 1862#endif 1863 __asm __volatile("mcr p15, 0, %0, c1, c0, 1" 1864 : : "r" (auxctl)); 1865} 1866#endif /* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */ 1867