1 /* $NetBSD: cpufunc.c,v 1.11 2001/07/09 19:51:14 reinoud 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 * Copyright (c) 1997 Mark Brinicombe. 8 * Copyright (c) 1997 Causality Limited 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by Causality Limited. 22 * 4. The name of Causality Limited may not be used to endorse or promote 23 * products derived from this software without specific prior written 24 * permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS 27 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 28 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 29 * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT, 30 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 32 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * RiscBSD kernel project 39 * 40 * cpufuncs.c 41 * 42 * C functions for supporting CPU / MMU / TLB specific operations. 43 * 44 * Created : 30/01/97 45 */ 46 47 #include "opt_compat_netbsd.h" 48 #include "opt_cputypes.h" 49 #include "opt_pmap_debug.h" 50 51 #include <sys/types.h> 52 #include <sys/param.h> 53 #include <sys/systm.h> 54 #include <machine/cpu.h> 55 #include <machine/cpufunc.h> 56 #include <machine/bootconfig.h> 57 #include <arch/arm/arm/disassem.h> 58 59 #ifdef CPU_ARM3 60 struct cpu_functions arm3_cpufuncs = { 61 /* CPU functions */ 62 63 cpufunc_id, /* id */ 64 65 /* MMU functions */ 66 67 arm3_control, /* control */ 68 NULL, /* domain */ 69 NULL, /* setttb */ 70 NULL, /* faultstatus */ 71 NULL, /* faultaddress */ 72 73 /* TLB functions */ 74 75 cpufunc_nullop, /* tlb_flushID */ 76 (void *)cpufunc_nullop, /* tlb_flushID_SE */ 77 cpufunc_nullop, /* tlb_flushI */ 78 (void *)cpufunc_nullop, /* tlb_flushI_SE */ 79 cpufunc_nullop, /* tlb_flushD */ 80 (void *)cpufunc_nullop, /* tlb_flushD_SE */ 81 82 /* Cache functions */ 83 84 arm3_cache_flush, /* cache_flushID */ 85 (void *)arm3_cache_flush, /* cache_flushID_SE */ 86 arm3_cache_flush, /* cache_flushI */ 87 (void *)arm3_cache_flush, /* cache_flushI_SE */ 88 arm3_cache_flush, /* cache_flushD */ 89 (void *)arm3_cache_flush, /* cache_flushD_SE */ 90 91 cpufunc_nullop, /* cache_cleanID s*/ 92 (void *)cpufunc_nullop, /* cache_cleanID_E s*/ 93 cpufunc_nullop, /* cache_cleanD s*/ 94 (void *)cpufunc_nullop, /* cache_cleanD_E */ 95 96 arm3_cache_flush, /* cache_purgeID s*/ 97 (void *)arm3_cache_flush, /* cache_purgeID_E s*/ 98 arm3_cache_flush, /* cache_purgeD s*/ 99 (void *)arm3_cache_flush, /* cache_purgeD_E s*/ 100 101 /* Other functions */ 102 103 cpufunc_nullop, /* flush_prefetchbuf */ 104 cpufunc_nullop, /* drain_writebuf */ 105 cpufunc_nullop, /* flush_brnchtgt_C */ 106 (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 107 108 (void *)cpufunc_nullop, /* sleep */ 109 110 /* Soft functions */ 111 112 cpufunc_nullop, /* cache_syncI */ 113 (void *)cpufunc_nullop, /* cache_cleanID_rng */ 114 (void *)cpufunc_nullop, /* cache_cleanD_rng */ 115 (void *)arm3_cache_flush, /* cache_purgeID_rng */ 116 (void *)arm3_cache_flush, /* cache_purgeD_rng */ 117 (void *)cpufunc_nullop, /* cache_syncI_rng */ 118 119 early_abort_fixup, /* dataabt_fixup */ 120 cpufunc_null_fixup, /* prefetchabt_fixup */ 121 122 NULL, /* context_switch */ 123 124 (void *)cpufunc_nullop /* cpu setup */ 125 126 }; 127 #endif /* CPU_ARM3 */ 128 129 #ifdef CPU_ARM6 130 struct cpu_functions arm6_cpufuncs = { 131 /* CPU functions */ 132 133 cpufunc_id, /* id */ 134 135 /* MMU functions */ 136 137 cpufunc_control, /* control */ 138 cpufunc_domains, /* domain */ 139 arm67_setttb, /* setttb */ 140 cpufunc_faultstatus, /* faultstatus */ 141 cpufunc_faultaddress, /* faultaddress */ 142 143 /* TLB functions */ 144 145 arm67_tlb_flush, /* tlb_flushID */ 146 arm67_tlb_purge, /* tlb_flushID_SE */ 147 arm67_tlb_flush, /* tlb_flushI */ 148 arm67_tlb_purge, /* tlb_flushI_SE */ 149 arm67_tlb_flush, /* tlb_flushD */ 150 arm67_tlb_purge, /* tlb_flushD_SE */ 151 152 /* Cache functions */ 153 154 arm67_cache_flush, /* cache_flushID */ 155 (void *)arm67_cache_flush, /* cache_flushID_SE */ 156 arm67_cache_flush, /* cache_flushI */ 157 (void *)arm67_cache_flush, /* cache_flushI_SE */ 158 arm67_cache_flush, /* cache_flushD */ 159 (void *)arm67_cache_flush, /* cache_flushD_SE */ 160 161 cpufunc_nullop, /* cache_cleanID s*/ 162 (void *)cpufunc_nullop, /* cache_cleanID_E s*/ 163 cpufunc_nullop, /* cache_cleanD s*/ 164 (void *)cpufunc_nullop, /* cache_cleanD_E */ 165 166 arm67_cache_flush, /* cache_purgeID s*/ 167 (void *)arm67_cache_flush, /* cache_purgeID_E s*/ 168 arm67_cache_flush, /* cache_purgeD s*/ 169 (void *)arm67_cache_flush, /* cache_purgeD_E s*/ 170 171 /* Other functions */ 172 173 cpufunc_nullop, /* flush_prefetchbuf */ 174 cpufunc_nullop, /* drain_writebuf */ 175 cpufunc_nullop, /* flush_brnchtgt_C */ 176 (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 177 178 (void *)cpufunc_nullop, /* sleep */ 179 180 /* Soft functions */ 181 182 cpufunc_nullop, /* cache_syncI */ 183 (void *)cpufunc_nullop, /* cache_cleanID_rng */ 184 (void *)cpufunc_nullop, /* cache_cleanD_rng */ 185 (void *)arm67_cache_flush, /* cache_purgeID_rng */ 186 (void *)arm67_cache_flush, /* cache_purgeD_rng */ 187 (void *)cpufunc_nullop, /* cache_syncI_rng */ 188 189 #ifdef ARM6_LATE_ABORT 190 late_abort_fixup, /* dataabt_fixup */ 191 #else 192 early_abort_fixup, /* dataabt_fixup */ 193 #endif 194 cpufunc_null_fixup, /* prefetchabt_fixup */ 195 196 arm67_context_switch, /* context_switch */ 197 198 arm6_setup /* cpu setup */ 199 200 }; 201 #endif /* CPU_ARM6 */ 202 203 #ifdef CPU_ARM7 204 struct cpu_functions arm7_cpufuncs = { 205 /* CPU functions */ 206 207 cpufunc_id, /* id */ 208 209 /* MMU functions */ 210 211 cpufunc_control, /* control */ 212 cpufunc_domains, /* domain */ 213 arm67_setttb, /* setttb */ 214 cpufunc_faultstatus, /* faultstatus */ 215 cpufunc_faultaddress, /* faultaddress */ 216 217 /* TLB functions */ 218 219 arm67_tlb_flush, /* tlb_flushID */ 220 arm67_tlb_purge, /* tlb_flushID_SE */ 221 arm67_tlb_flush, /* tlb_flushI */ 222 arm67_tlb_purge, /* tlb_flushI_SE */ 223 arm67_tlb_flush, /* tlb_flushD */ 224 arm67_tlb_purge, /* tlb_flushD_SE */ 225 226 /* Cache functions */ 227 228 arm67_cache_flush, /* cache_flushID */ 229 (void *)arm67_cache_flush, /* cache_flushID_SE */ 230 arm67_cache_flush, /* cache_flushI */ 231 (void *)arm67_cache_flush, /* cache_flushI_SE */ 232 arm67_cache_flush, /* cache_flushD */ 233 (void *)arm67_cache_flush, /* cache_flushD_SE */ 234 235 cpufunc_nullop, /* cache_cleanID s*/ 236 (void *)cpufunc_nullop, /* cache_cleanID_E s*/ 237 cpufunc_nullop, /* cache_cleanD s*/ 238 (void *)cpufunc_nullop, /* cache_cleanD_E */ 239 240 arm67_cache_flush, /* cache_purgeID s*/ 241 (void *)arm67_cache_flush, /* cache_purgeID_E s*/ 242 arm67_cache_flush, /* cache_purgeD s*/ 243 (void *)arm67_cache_flush, /* cache_purgeD_E s*/ 244 245 /* Other functions */ 246 247 cpufunc_nullop, /* flush_prefetchbuf */ 248 cpufunc_nullop, /* drain_writebuf */ 249 cpufunc_nullop, /* flush_brnchtgt_C */ 250 (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 251 252 (void *)cpufunc_nullop, /* sleep */ 253 254 /* Soft functions */ 255 256 cpufunc_nullop, /* cache_syncI */ 257 (void *)cpufunc_nullop, /* cache_cleanID_rng */ 258 (void *)cpufunc_nullop, /* cache_cleanD_rng */ 259 (void *)arm67_cache_flush, /* cache_purgeID_rng */ 260 (void *)arm67_cache_flush, /* cache_purgeD_rng */ 261 (void *)cpufunc_nullop, /* cache_syncI_rng */ 262 263 late_abort_fixup, /* dataabt_fixup */ 264 cpufunc_null_fixup, /* prefetchabt_fixup */ 265 266 arm67_context_switch, /* context_switch */ 267 268 arm7_setup /* cpu setup */ 269 270 }; 271 #endif /* CPU_ARM7 */ 272 273 #ifdef CPU_ARM7TDMI 274 struct cpu_functions arm7tdmi_cpufuncs = { 275 /* CPU functions */ 276 277 cpufunc_id, /* id */ 278 279 /* MMU functions */ 280 281 cpufunc_control, /* control */ 282 cpufunc_domains, /* domain */ 283 arm7tdmi_setttb, /* setttb */ 284 cpufunc_faultstatus, /* faultstatus */ 285 cpufunc_faultaddress, /* faultaddress */ 286 287 /* TLB functions */ 288 289 arm7tdmi_tlb_flushID, /* tlb_flushID */ 290 arm7tdmi_tlb_flushID_SE, /* tlb_flushID_SE */ 291 arm7tdmi_tlb_flushID, /* tlb_flushI */ 292 arm7tdmi_tlb_flushID_SE, /* tlb_flushI_SE */ 293 arm7tdmi_tlb_flushID, /* tlb_flushD */ 294 arm7tdmi_tlb_flushID_SE, /* tlb_flushD_SE */ 295 296 /* Cache functions */ 297 298 arm7tdmi_cache_flushID, /* cache_flushID */ 299 (void *)arm7tdmi_cache_flushID, /* cache_flushID_SE */ 300 arm7tdmi_cache_flushID, /* cache_flushI */ 301 (void *)arm7tdmi_cache_flushID, /* cache_flushI_SE */ 302 arm7tdmi_cache_flushID, /* cache_flushD */ 303 (void *)arm7tdmi_cache_flushID, /* cache_flushD_SE */ 304 305 cpufunc_nullop, /* cache_cleanID s*/ 306 (void *)cpufunc_nullop, /* cache_cleanID_E s*/ 307 cpufunc_nullop, /* cache_cleanD s*/ 308 (void *)cpufunc_nullop, /* cache_cleanD_E */ 309 310 arm7tdmi_cache_flushID, /* cache_purgeID s*/ 311 (void *)arm7tdmi_cache_flushID, /* cache_purgeID_E s*/ 312 arm7tdmi_cache_flushID, /* cache_purgeD s*/ 313 (void *)arm7tdmi_cache_flushID, /* cache_purgeD_E s*/ 314 315 /* Other functions */ 316 317 cpufunc_nullop, /* flush_prefetchbuf */ 318 cpufunc_nullop, /* drain_writebuf */ 319 cpufunc_nullop, /* flush_brnchtgt_C */ 320 (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 321 322 (void *)cpufunc_nullop, /* sleep */ 323 324 /* Soft functions */ 325 326 cpufunc_nullop, /* cache_syncI */ 327 (void *)cpufunc_nullop, /* cache_cleanID_rng */ 328 (void *)cpufunc_nullop, /* cache_cleanD_rng */ 329 (void *)arm7tdmi_cache_flushID, /* cache_purgeID_rng */ 330 (void *)arm7tdmi_cache_flushID, /* cache_purgeD_rng */ 331 (void *)cpufunc_nullop, /* cache_syncI_rng */ 332 333 late_abort_fixup, /* dataabt_fixup */ 334 cpufunc_null_fixup, /* prefetchabt_fixup */ 335 336 arm7tdmi_context_switch, /* context_switch */ 337 338 arm7tdmi_setup /* cpu setup */ 339 340 }; 341 #endif /* CPU_ARM7TDMI */ 342 343 #ifdef CPU_ARM8 344 struct cpu_functions arm8_cpufuncs = { 345 /* CPU functions */ 346 347 cpufunc_id, /* id */ 348 349 /* MMU functions */ 350 351 cpufunc_control, /* control */ 352 cpufunc_domains, /* domain */ 353 arm8_setttb, /* setttb */ 354 cpufunc_faultstatus, /* faultstatus */ 355 cpufunc_faultaddress, /* faultaddress */ 356 357 /* TLB functions */ 358 359 arm8_tlb_flushID, /* tlb_flushID */ 360 arm8_tlb_flushID_SE, /* tlb_flushID_SE */ 361 arm8_tlb_flushID, /* tlb_flushI */ 362 arm8_tlb_flushID_SE, /* tlb_flushI_SE */ 363 arm8_tlb_flushID, /* tlb_flushD */ 364 arm8_tlb_flushID_SE, /* tlb_flushD_SE */ 365 366 /* Cache functions */ 367 368 arm8_cache_flushID, /* cache_flushID */ 369 arm8_cache_flushID_E, /* cache_flushID_SE */ 370 arm8_cache_flushID, /* cache_flushI */ 371 arm8_cache_flushID_E, /* cache_flushI_SE */ 372 arm8_cache_flushID, /* cache_flushD */ 373 arm8_cache_flushID_E, /* cache_flushD_SE */ 374 375 arm8_cache_cleanID, /* cache_cleanID s*/ 376 arm8_cache_cleanID_E, /* cache_cleanID_E s*/ 377 arm8_cache_cleanID, /* cache_cleanD s*/ 378 arm8_cache_cleanID_E, /* cache_cleanD_E */ 379 380 arm8_cache_purgeID, /* cache_purgeID s*/ 381 arm8_cache_purgeID_E, /* cache_purgeID_E s*/ 382 arm8_cache_purgeID, /* cache_purgeD s*/ 383 arm8_cache_purgeID_E, /* cache_purgeD_E s*/ 384 385 /* Other functions */ 386 387 cpufunc_nullop, /* flush_prefetchbuf */ 388 cpufunc_nullop, /* drain_writebuf */ 389 cpufunc_nullop, /* flush_brnchtgt_C */ 390 (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 391 392 (void *)cpufunc_nullop, /* sleep */ 393 394 /* Soft functions */ 395 396 (void *)cpufunc_nullop, /* cache_syncI */ 397 (void *)arm8_cache_cleanID, /* cache_cleanID_rng */ 398 (void *)arm8_cache_cleanID, /* cache_cleanD_rng */ 399 (void *)arm8_cache_purgeID, /* cache_purgeID_rng */ 400 (void *)arm8_cache_purgeID, /* cache_purgeD_rng */ 401 (void *)cpufunc_nullop, /* cache_syncI_rng */ 402 403 cpufunc_null_fixup, /* dataabt_fixup */ 404 cpufunc_null_fixup, /* prefetchabt_fixup */ 405 406 arm8_context_switch, /* context_switch */ 407 408 arm8_setup /* cpu setup */ 409 }; 410 #endif /* CPU_ARM8 */ 411 412 #ifdef CPU_SA110 413 struct cpu_functions sa110_cpufuncs = { 414 /* CPU functions */ 415 416 cpufunc_id, /* id */ 417 418 /* MMU functions */ 419 420 cpufunc_control, /* control */ 421 cpufunc_domains, /* domain */ 422 sa110_setttb, /* setttb */ 423 cpufunc_faultstatus, /* faultstatus */ 424 cpufunc_faultaddress, /* faultaddress */ 425 426 /* TLB functions */ 427 428 sa110_tlb_flushID, /* tlb_flushID */ 429 sa110_tlb_flushID_SE, /* tlb_flushID_SE */ 430 sa110_tlb_flushI, /* tlb_flushI */ 431 (void *)sa110_tlb_flushI, /* tlb_flushI_SE */ 432 sa110_tlb_flushD, /* tlb_flushD */ 433 sa110_tlb_flushD_SE, /* tlb_flushD_SE */ 434 435 /* Cache functions */ 436 437 sa110_cache_flushID, /* cache_flushID */ 438 (void *)sa110_cache_flushID, /* cache_flushID_SE */ 439 sa110_cache_flushI, /* cache_flushI */ 440 (void *)sa110_cache_flushI, /* cache_flushI_SE */ 441 sa110_cache_flushD, /* cache_flushD */ 442 sa110_cache_flushD_SE, /* cache_flushD_SE */ 443 444 sa110_cache_cleanID, /* cache_cleanID s*/ 445 sa110_cache_cleanD_E, /* cache_cleanID_E s*/ 446 sa110_cache_cleanD, /* cache_cleanD s*/ 447 sa110_cache_cleanD_E, /* cache_cleanD_E */ 448 449 sa110_cache_purgeID, /* cache_purgeID s*/ 450 sa110_cache_purgeID_E, /* cache_purgeID_E s*/ 451 sa110_cache_purgeD, /* cache_purgeD s*/ 452 sa110_cache_purgeD_E, /* cache_purgeD_E s*/ 453 454 /* Other functions */ 455 456 cpufunc_nullop, /* flush_prefetchbuf */ 457 sa110_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 sa110_cache_syncI, /* cache_syncI */ 466 sa110_cache_cleanID_rng, /* cache_cleanID_rng */ 467 sa110_cache_cleanD_rng, /* cache_cleanD_rng */ 468 sa110_cache_purgeID_rng, /* cache_purgeID_rng */ 469 sa110_cache_purgeD_rng, /* cache_purgeD_rng */ 470 sa110_cache_syncI_rng, /* cache_syncI_rng */ 471 472 cpufunc_null_fixup, /* dataabt_fixup */ 473 cpufunc_null_fixup, /* prefetchabt_fixup */ 474 475 sa110_context_switch, /* context_switch */ 476 477 sa110_setup /* cpu setup */ 478 }; 479 #endif /* CPU_SA110 */ 480 481 482 /* 483 * Global constants also used by locore.s 484 */ 485 486 struct cpu_functions cpufuncs; 487 u_int cputype; 488 u_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore.s */ 489 490 /* 491 * Cannot panic here as we may not have a console yet ... 492 */ 493 494 int 495 set_cpufuncs() 496 { 497 cputype = cpufunc_id(); 498 cputype &= CPU_ID_CPU_MASK; 499 500 501 #ifdef CPU_ARM3 502 if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD && 503 (cputype & 0x00000f00) == 0x00000300) { 504 cpufuncs = arm3_cpufuncs; 505 cpu_reset_needs_v4_MMU_disable = 0; 506 return 0; 507 } 508 #endif /* CPU_ARM3 */ 509 #ifdef CPU_ARM6 510 if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD && 511 (cputype & 0x00000f00) == 0x00000600) { 512 cpufuncs = arm6_cpufuncs; 513 cpu_reset_needs_v4_MMU_disable = 0; 514 return 0; 515 } 516 #endif /* CPU_ARM6 */ 517 #ifdef CPU_ARM7 518 if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD && 519 CPU_ID_IS7(cputype) && 520 (cputype & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V3) { 521 cpufuncs = arm7_cpufuncs; 522 cpu_reset_needs_v4_MMU_disable = 0; 523 return 0; 524 } 525 #endif /* CPU_ARM7 */ 526 #ifdef CPU_ARM7TDMI 527 if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD && 528 CPU_ID_IS7(cputype) && 529 (cputype & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V4T) { 530 cpufuncs = arm7tdmi_cpufuncs; 531 cpu_reset_needs_v4_MMU_disable = 0; 532 return 0; 533 } 534 #endif 535 #ifdef CPU_ARM8 536 if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD && 537 (cputype & 0x0000f000) == 0x00008000) { 538 cpufuncs = arm8_cpufuncs; 539 cpu_reset_needs_v4_MMU_disable = 0; /* XXX correct? */ 540 return 0; 541 } 542 #endif /* CPU_ARM8 */ 543 #ifdef CPU_SA110 544 if (cputype == CPU_ID_SA110 || cputype == CPU_ID_SA1100 || 545 cputype == CPU_ID_SA1110) { 546 cpufuncs = sa110_cpufuncs; 547 cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */ 548 return 0; 549 } 550 #endif /* CPU_SA110 */ 551 /* 552 * Bzzzz. And the answer was ... 553 */ 554 /* panic("No support for this CPU type (%08x) in kernel", cputype);*/ 555 return(ARCHITECTURE_NOT_PRESENT); 556 } 557 558 /* 559 * Fixup routines for data and prefetch aborts. 560 * 561 * Several compile time symbols are used 562 * 563 * DEBUG_FAULT_CORRECTION - Print debugging information during the 564 * correction of registers after a fault. 565 * ARM6_LATE_ABORT - ARM6 supports both early and late aborts 566 * when defined should use late aborts 567 */ 568 569 #if defined(DEBUG_FAULT_CORRECTION) && !defined(PMAP_DEBUG) 570 #error PMAP_DEBUG must be defined to use DEBUG_FAULT_CORRECTION 571 #endif 572 573 /* 574 * Null abort fixup routine. 575 * For use when no fixup is required. 576 */ 577 int 578 cpufunc_null_fixup(arg) 579 void *arg; 580 { 581 return(ABORT_FIXUP_OK); 582 } 583 584 #if defined(CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI) 585 #ifdef DEBUG_FAULT_CORRECTION 586 extern int pmap_debug_level; 587 #endif 588 #endif 589 590 #if defined(CPU_ARM2) || defined(CPU_ARM250) || defined(CPU_ARM3) || \ 591 defined(CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI) 592 /* 593 * "Early" data abort fixup. 594 * 595 * For ARM2, ARM2as, ARM3 and ARM6 (in early-abort mode). Also used 596 * indirectly by ARM6 (in late-abort mode) and ARM7[TDMI]. 597 * 598 * In early aborts, we may have to fix up LDM, STM, LDC and STC. 599 */ 600 int 601 early_abort_fixup(arg) 602 void *arg; 603 { 604 trapframe_t *frame = arg; 605 u_int fault_pc; 606 u_int fault_instruction; 607 int saved_lr = 0; 608 609 if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { 610 611 /* Ok an abort in SVC mode */ 612 613 /* 614 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage 615 * as the fault happened in svc mode but we need it in the 616 * usr slot so we can treat the registers as an array of ints 617 * during fixing. 618 * NOTE: This PC is in the position but writeback is not 619 * allowed on r15. 620 * Doing it like this is more efficient than trapping this 621 * case in all possible locations in the following fixup code. 622 */ 623 624 saved_lr = frame->tf_usr_lr; 625 frame->tf_usr_lr = frame->tf_svc_lr; 626 627 /* 628 * Note the trapframe does not have the SVC r13 so a fault 629 * from an instruction with writeback to r13 in SVC mode is 630 * not allowed. This should not happen as the kstack is 631 * always valid. 632 */ 633 } 634 635 /* Get fault address and status from the CPU */ 636 637 fault_pc = frame->tf_pc; 638 fault_instruction = *((volatile unsigned int *)fault_pc); 639 640 /* Decode the fault instruction and fix the registers as needed */ 641 642 if ((fault_instruction & 0x0e000000) == 0x08000000) { 643 int base; 644 int loop; 645 int count; 646 int *registers = &frame->tf_r0; 647 648 #ifdef DEBUG_FAULT_CORRECTION 649 if (pmap_debug_level >= 0) { 650 printf("LDM/STM\n"); 651 disassemble(fault_pc); 652 } 653 #endif /* DEBUG_FAULT_CORRECTION */ 654 if (fault_instruction & (1 << 21)) { 655 #ifdef DEBUG_FAULT_CORRECTION 656 if (pmap_debug_level >= 0) 657 printf("This instruction must be corrected\n"); 658 #endif /* DEBUG_FAULT_CORRECTION */ 659 base = (fault_instruction >> 16) & 0x0f; 660 if (base == 15) 661 return ABORT_FIXUP_FAILED; 662 /* Count registers transferred */ 663 count = 0; 664 for (loop = 0; loop < 16; ++loop) { 665 if (fault_instruction & (1<<loop)) 666 ++count; 667 } 668 #ifdef DEBUG_FAULT_CORRECTION 669 if (pmap_debug_level >= 0) { 670 printf("%d registers used\n", count); 671 printf("Corrected r%d by %d bytes ", base, count * 4); 672 } 673 #endif /* DEBUG_FAULT_CORRECTION */ 674 if (fault_instruction & (1 << 23)) { 675 #ifdef DEBUG_FAULT_CORRECTION 676 if (pmap_debug_level >= 0) 677 printf("down\n"); 678 #endif /* DEBUG_FAULT_CORRECTION */ 679 registers[base] -= count * 4; 680 } else { 681 #ifdef DEBUG_FAULT_CORRECTION 682 if (pmap_debug_level >= 0) 683 printf("up\n"); 684 #endif /* DEBUG_FAULT_CORRECTION */ 685 registers[base] += count * 4; 686 } 687 } 688 } else if ((fault_instruction & 0x0e000000) == 0x0c000000) { 689 int base; 690 int offset; 691 int *registers = &frame->tf_r0; 692 693 /* REGISTER CORRECTION IS REQUIRED FOR THESE INSTRUCTIONS */ 694 695 #ifdef DEBUG_FAULT_CORRECTION 696 if (pmap_debug_level >= 0) 697 disassemble(fault_pc); 698 #endif /* DEBUG_FAULT_CORRECTION */ 699 700 /* Only need to fix registers if write back is turned on */ 701 702 if ((fault_instruction & (1 << 21)) != 0) { 703 base = (fault_instruction >> 16) & 0x0f; 704 if (base == 13 && (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) 705 return ABORT_FIXUP_FAILED; 706 if (base == 15) 707 return ABORT_FIXUP_FAILED; 708 709 offset = (fault_instruction & 0xff) << 2; 710 #ifdef DEBUG_FAULT_CORRECTION 711 if (pmap_debug_level >= 0) 712 printf("r%d=%08x\n", base, registers[base]); 713 #endif /* DEBUG_FAULT_CORRECTION */ 714 if ((fault_instruction & (1 << 23)) != 0) 715 offset = -offset; 716 registers[base] += offset; 717 #ifdef DEBUG_FAULT_CORRECTION 718 if (pmap_debug_level >= 0) 719 printf("r%d=%08x\n", base, registers[base]); 720 #endif /* DEBUG_FAULT_CORRECTION */ 721 } 722 } else if ((fault_instruction & 0x0e000000) == 0x0c000000) 723 return ABORT_FIXUP_FAILED; 724 725 if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { 726 727 /* Ok an abort in SVC mode */ 728 729 /* 730 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage 731 * as the fault happened in svc mode but we need it in the 732 * usr slot so we can treat the registers as an array of ints 733 * during fixing. 734 * NOTE: This PC is in the position but writeback is not 735 * allowed on r15. 736 * Doing it like this is more efficient than trapping this 737 * case in all possible locations in the prior fixup code. 738 */ 739 740 frame->tf_svc_lr = frame->tf_usr_lr; 741 frame->tf_usr_lr = saved_lr; 742 743 /* 744 * Note the trapframe does not have the SVC r13 so a fault 745 * from an instruction with writeback to r13 in SVC mode is 746 * not allowed. This should not happen as the kstack is 747 * always valid. 748 */ 749 } 750 751 return(ABORT_FIXUP_OK); 752 } 753 #endif /* CPU_ARM2/250/3/6/7 */ 754 755 #if (defined(CPU_ARM6) && defined(ARM6_LATE_ABORT)) || defined(CPU_ARM7) || \ 756 defined(CPU_ARM7TDMI) 757 /* 758 * "Late" (base updated) data abort fixup 759 * 760 * For ARM6 (in late-abort mode) and ARM7. 761 * 762 * In this model, all data-transfer instructions need fixing up. We defer 763 * LDM, STM, LDC and STC fixup to the early-abort handler. 764 */ 765 int 766 late_abort_fixup(arg) 767 void *arg; 768 { 769 trapframe_t *frame = arg; 770 u_int fault_pc; 771 u_int fault_instruction; 772 int saved_lr = 0; 773 774 if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { 775 776 /* Ok an abort in SVC mode */ 777 778 /* 779 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage 780 * as the fault happened in svc mode but we need it in the 781 * usr slot so we can treat the registers as an array of ints 782 * during fixing. 783 * NOTE: This PC is in the position but writeback is not 784 * allowed on r15. 785 * Doing it like this is more efficient than trapping this 786 * case in all possible locations in the following fixup code. 787 */ 788 789 saved_lr = frame->tf_usr_lr; 790 frame->tf_usr_lr = frame->tf_svc_lr; 791 792 /* 793 * Note the trapframe does not have the SVC r13 so a fault 794 * from an instruction with writeback to r13 in SVC mode is 795 * not allowed. This should not happen as the kstack is 796 * always valid. 797 */ 798 } 799 800 /* Get fault address and status from the CPU */ 801 802 fault_pc = frame->tf_pc; 803 fault_instruction = *((volatile unsigned int *)fault_pc); 804 805 /* Decode the fault instruction and fix the registers as needed */ 806 807 /* Was is a swap instruction ? */ 808 809 if ((fault_instruction & 0x0fb00ff0) == 0x01000090) { 810 #ifdef DEBUG_FAULT_CORRECTION 811 if (pmap_debug_level >= 0) 812 disassemble(fault_pc); 813 #endif /* DEBUG_FAULT_CORRECTION */ 814 } else if ((fault_instruction & 0x0c000000) == 0x04000000) { 815 816 /* Was is a ldr/str instruction */ 817 /* This is for late abort only */ 818 819 int base; 820 int offset; 821 int *registers = &frame->tf_r0; 822 823 #ifdef DEBUG_FAULT_CORRECTION 824 if (pmap_debug_level >= 0) 825 disassemble(fault_pc); 826 #endif /* DEBUG_FAULT_CORRECTION */ 827 828 /* This is for late abort only */ 829 830 if ((fault_instruction & (1 << 24)) == 0 831 || (fault_instruction & (1 << 21)) != 0) { 832 base = (fault_instruction >> 16) & 0x0f; 833 if (base == 13 && (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) 834 return ABORT_FIXUP_FAILED; 835 if (base == 15) 836 return ABORT_FIXUP_FAILED; 837 #ifdef DEBUG_FAULT_CORRECTION 838 if (pmap_debug_level >=0) 839 printf("late abt fix: r%d=%08x ", base, registers[base]); 840 #endif /* DEBUG_FAULT_CORRECTION */ 841 if ((fault_instruction & (1 << 25)) == 0) { 842 /* Immediate offset - easy */ 843 offset = fault_instruction & 0xfff; 844 if ((fault_instruction & (1 << 23))) 845 offset = -offset; 846 registers[base] += offset; 847 #ifdef DEBUG_FAULT_CORRECTION 848 if (pmap_debug_level >=0) 849 printf("imm=%08x ", offset); 850 #endif /* DEBUG_FAULT_CORRECTION */ 851 } else { 852 int shift; 853 854 offset = fault_instruction & 0x0f; 855 if (offset == base) 856 return ABORT_FIXUP_FAILED; 857 858 /* Register offset - hard we have to cope with shifts ! */ 859 offset = registers[offset]; 860 861 if ((fault_instruction & (1 << 4)) == 0) 862 shift = (fault_instruction >> 7) & 0x1f; 863 else { 864 if ((fault_instruction & (1 << 7)) != 0) 865 return ABORT_FIXUP_FAILED; 866 shift = ((fault_instruction >> 8) & 0xf); 867 if (base == shift) 868 return ABORT_FIXUP_FAILED; 869 #ifdef DEBUG_FAULT_CORRECTION 870 if (pmap_debug_level >=0) 871 printf("shift reg=%d ", shift); 872 #endif /* DEBUG_FAULT_CORRECTION */ 873 shift = registers[shift]; 874 } 875 #ifdef DEBUG_FAULT_CORRECTION 876 if (pmap_debug_level >=0) 877 printf("shift=%08x ", shift); 878 #endif /* DEBUG_FAULT_CORRECTION */ 879 switch (((fault_instruction >> 5) & 0x3)) { 880 case 0 : /* Logical left */ 881 offset = (int)(((u_int)offset) << shift); 882 break; 883 case 1 : /* Logical Right */ 884 if (shift == 0) shift = 32; 885 offset = (int)(((u_int)offset) >> shift); 886 break; 887 case 2 : /* Arithmetic Right */ 888 if (shift == 0) shift = 32; 889 offset = (int)(((int)offset) >> shift); 890 break; 891 case 3 : /* Rotate right */ 892 return ABORT_FIXUP_FAILED; 893 } 894 895 #ifdef DEBUG_FAULT_CORRECTION 896 if (pmap_debug_level >=0) 897 printf("abt: fixed LDR/STR with register offset\n"); 898 #endif /* DEBUG_FAULT_CORRECTION */ 899 if ((fault_instruction & (1 << 23))) 900 offset = -offset; 901 #ifdef DEBUG_FAULT_CORRECTION 902 if (pmap_debug_level >=0) 903 printf("offset=%08x ", offset); 904 #endif /* DEBUG_FAULT_CORRECTION */ 905 registers[base] += offset; 906 } 907 #ifdef DEBUG_FAULT_CORRECTION 908 if (pmap_debug_level >=0) 909 printf("r%d=%08x\n", base, registers[base]); 910 #endif /* DEBUG_FAULT_CORRECTION */ 911 } 912 } 913 914 if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { 915 916 /* Ok an abort in SVC mode */ 917 918 /* 919 * Copy the SVC r14 into the usr r14 - The usr r14 is garbage 920 * as the fault happened in svc mode but we need it in the 921 * usr slot so we can treat the registers as an array of ints 922 * during fixing. 923 * NOTE: This PC is in the position but writeback is not 924 * allowed on r15. 925 * Doing it like this is more efficient than trapping this 926 * case in all possible locations in the prior fixup code. 927 */ 928 929 frame->tf_svc_lr = frame->tf_usr_lr; 930 frame->tf_usr_lr = saved_lr; 931 932 /* 933 * Note the trapframe does not have the SVC r13 so a fault 934 * from an instruction with writeback to r13 in SVC mode is 935 * not allowed. This should not happen as the kstack is 936 * always valid. 937 */ 938 } 939 940 /* 941 * Now let the early-abort fixup routine have a go, in case it 942 * was an LDM, STM, LDC or STC that faulted. 943 */ 944 945 return early_abort_fixup(arg); 946 } 947 #endif /* CPU_ARM6(LATE)/7/7TDMI */ 948 949 /* 950 * CPU Setup code 951 */ 952 953 #if defined(CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI) || \ 954 defined(CPU_ARM8) || defined(CPU_SA110) 955 int cpuctrl; 956 957 #define IGN 0 958 #define OR 1 959 #define BIC 2 960 961 struct cpu_option { 962 char *co_name; 963 int co_falseop; 964 int co_trueop; 965 int co_value; 966 }; 967 968 static u_int 969 parse_cpu_options(args, optlist, cpuctrl) 970 char *args; 971 struct cpu_option *optlist; 972 u_int cpuctrl; 973 { 974 int integer; 975 976 while (optlist->co_name) { 977 if (get_bootconf_option(args, optlist->co_name, 978 BOOTOPT_TYPE_BOOLEAN, &integer)) { 979 if (integer) { 980 if (optlist->co_trueop == OR) 981 cpuctrl |= optlist->co_value; 982 else if (optlist->co_trueop == BIC) 983 cpuctrl &= ~optlist->co_value; 984 } else { 985 if (optlist->co_falseop == OR) 986 cpuctrl |= optlist->co_value; 987 else if (optlist->co_falseop == BIC) 988 cpuctrl &= ~optlist->co_value; 989 } 990 } 991 ++optlist; 992 } 993 return(cpuctrl); 994 } 995 #endif /* CPU_ARM6 || CPU_ARM7 || CPU_ARM7TDMI || CPU_ARM8 || CPU_SA110 */ 996 997 #if defined (CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI) \ 998 || defined(CPU_ARM8) 999 struct cpu_option arm678_options[] = { 1000 #ifdef COMPAT_12 1001 { "nocache", IGN, BIC, CPU_CONTROL_IDC_ENABLE }, 1002 { "nowritebuf", IGN, BIC, CPU_CONTROL_WBUF_ENABLE }, 1003 #endif /* COMPAT_12 */ 1004 { "cpu.cache", BIC, OR, CPU_CONTROL_IDC_ENABLE }, 1005 { "cpu.nocache", OR, BIC, CPU_CONTROL_IDC_ENABLE }, 1006 { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1007 { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1008 { NULL, IGN, IGN, 0 } 1009 }; 1010 1011 #endif /* CPU_ARM6 || CPU_ARM7 || CPU_ARM7TDMI || CPU_ARM8 */ 1012 1013 #ifdef CPU_ARM6 1014 struct cpu_option arm6_options[] = { 1015 { "arm6.cache", BIC, OR, CPU_CONTROL_IDC_ENABLE }, 1016 { "arm6.nocache", OR, BIC, CPU_CONTROL_IDC_ENABLE }, 1017 { "arm6.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1018 { "arm6.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1019 { NULL, IGN, IGN, 0 } 1020 }; 1021 1022 void 1023 arm6_setup(args) 1024 char *args; 1025 { 1026 int cpuctrlmask; 1027 1028 /* Set up default control registers bits */ 1029 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1030 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1031 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE; 1032 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1033 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1034 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE 1035 | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_BEND_ENABLE 1036 | CPU_CONTROL_AFLT_ENABLE; 1037 1038 #ifdef ARM6_LATE_ABORT 1039 cpuctrl |= CPU_CONTROL_LABT_ENABLE; 1040 #endif /* ARM6_LATE_ABORT */ 1041 1042 cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl); 1043 cpuctrl = parse_cpu_options(args, arm6_options, cpuctrl); 1044 1045 /* Clear out the cache */ 1046 cpu_cache_purgeID(); 1047 1048 /* Set the control register */ 1049 cpu_control(0xffffffff, cpuctrl); 1050 } 1051 #endif /* CPU_ARM6 */ 1052 1053 #ifdef CPU_ARM7 1054 struct cpu_option arm7_options[] = { 1055 { "arm7.cache", BIC, OR, CPU_CONTROL_IDC_ENABLE }, 1056 { "arm7.nocache", OR, BIC, CPU_CONTROL_IDC_ENABLE }, 1057 { "arm7.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1058 { "arm7.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1059 #ifdef COMPAT_12 1060 { "fpaclk2", BIC, OR, CPU_CONTROL_CPCLK }, 1061 #endif /* COMPAT_12 */ 1062 { "arm700.fpaclk", BIC, OR, CPU_CONTROL_CPCLK }, 1063 { NULL, IGN, IGN, 0 } 1064 }; 1065 1066 void 1067 arm7_setup(args) 1068 char *args; 1069 { 1070 int cpuctrlmask; 1071 1072 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1073 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1074 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE; 1075 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1076 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1077 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE 1078 | CPU_CONTROL_CPCLK | CPU_CONTROL_LABT_ENABLE 1079 | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_BEND_ENABLE 1080 | CPU_CONTROL_AFLT_ENABLE; 1081 1082 cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl); 1083 cpuctrl = parse_cpu_options(args, arm7_options, cpuctrl); 1084 1085 /* Clear out the cache */ 1086 cpu_cache_purgeID(); 1087 1088 /* Set the control register */ 1089 cpu_control(0xffffffff, cpuctrl); 1090 } 1091 #endif /* CPU_ARM7 */ 1092 1093 #ifdef CPU_ARM7TDMI 1094 struct cpu_option arm7tdmi_options[] = { 1095 { "arm7.cache", BIC, OR, CPU_CONTROL_IDC_ENABLE }, 1096 { "arm7.nocache", OR, BIC, CPU_CONTROL_IDC_ENABLE }, 1097 { "arm7.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1098 { "arm7.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1099 #ifdef COMPAT_12 1100 { "fpaclk2", BIC, OR, CPU_CONTROL_CPCLK }, 1101 #endif /* COMPAT_12 */ 1102 { "arm700.fpaclk", BIC, OR, CPU_CONTROL_CPCLK }, 1103 { NULL, IGN, IGN, 0 } 1104 }; 1105 1106 void 1107 arm7tdmi_setup(args) 1108 char *args; 1109 { 1110 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1111 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1112 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE; 1113 1114 cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl); 1115 cpuctrl = parse_cpu_options(args, arm7tdmi_options, cpuctrl); 1116 1117 /* Clear out the cache */ 1118 cpu_cache_purgeID(); 1119 1120 /* Set the control register */ 1121 cpu_control(0xffffffff, cpuctrl); 1122 } 1123 #endif /* CPU_ARM7TDMI */ 1124 1125 #ifdef CPU_ARM8 1126 struct cpu_option arm8_options[] = { 1127 { "arm8.cache", BIC, OR, CPU_CONTROL_IDC_ENABLE }, 1128 { "arm8.nocache", OR, BIC, CPU_CONTROL_IDC_ENABLE }, 1129 { "arm8.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1130 { "arm8.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1131 #ifdef COMPAT_12 1132 { "branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, 1133 #endif /* COMPAT_12 */ 1134 { "cpu.branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, 1135 { "arm8.branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, 1136 { NULL, IGN, IGN, 0 } 1137 }; 1138 1139 void 1140 arm8_setup(args) 1141 char *args; 1142 { 1143 int integer; 1144 int cpuctrlmask; 1145 int clocktest; 1146 int setclock = 0; 1147 1148 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1149 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1150 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE; 1151 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1152 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1153 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE 1154 | CPU_CONTROL_BPRD_ENABLE | CPU_CONTROL_ROM_ENABLE 1155 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE; 1156 1157 cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl); 1158 cpuctrl = parse_cpu_options(args, arm8_options, cpuctrl); 1159 1160 /* Get clock configuration */ 1161 clocktest = arm8_clock_config(0, 0) & 0x0f; 1162 1163 /* Special ARM8 clock and test configuration */ 1164 if (get_bootconf_option(args, "arm8.clock.reset", BOOTOPT_TYPE_BOOLEAN, &integer)) { 1165 clocktest = 0; 1166 setclock = 1; 1167 } 1168 if (get_bootconf_option(args, "arm8.clock.dynamic", BOOTOPT_TYPE_BOOLEAN, &integer)) { 1169 if (integer) 1170 clocktest |= 0x01; 1171 else 1172 clocktest &= ~(0x01); 1173 setclock = 1; 1174 } 1175 if (get_bootconf_option(args, "arm8.clock.sync", BOOTOPT_TYPE_BOOLEAN, &integer)) { 1176 if (integer) 1177 clocktest |= 0x02; 1178 else 1179 clocktest &= ~(0x02); 1180 setclock = 1; 1181 } 1182 if (get_bootconf_option(args, "arm8.clock.fast", BOOTOPT_TYPE_BININT, &integer)) { 1183 clocktest = (clocktest & ~0xc0) | (integer & 3) << 2; 1184 setclock = 1; 1185 } 1186 if (get_bootconf_option(args, "arm8.test", BOOTOPT_TYPE_BININT, &integer)) { 1187 clocktest |= (integer & 7) << 5; 1188 setclock = 1; 1189 } 1190 1191 /* Clear out the cache */ 1192 cpu_cache_purgeID(); 1193 1194 /* Set the control register */ 1195 cpu_control(0xffffffff, cpuctrl); 1196 1197 /* Set the clock/test register */ 1198 if (setclock) 1199 arm8_clock_config(0x7f, clocktest); 1200 } 1201 #endif /* CPU_ARM8 */ 1202 1203 #ifdef CPU_SA110 1204 struct cpu_option sa110_options[] = { 1205 #ifdef COMPAT_12 1206 { "nocache", IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1207 { "nowritebuf", IGN, BIC, CPU_CONTROL_WBUF_ENABLE }, 1208 #endif /* COMPAT_12 */ 1209 { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1210 { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1211 { "sa110.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1212 { "sa110.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, 1213 { "sa110.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, 1214 { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1215 { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1216 { "sa110.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1217 { NULL, IGN, IGN, 0 } 1218 }; 1219 1220 void 1221 sa110_setup(args) 1222 char *args; 1223 { 1224 int cpuctrlmask; 1225 1226 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1227 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1228 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1229 | CPU_CONTROL_WBUF_ENABLE; 1230 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1231 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1232 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1233 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 1234 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 1235 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE 1236 | CPU_CONTROL_CPCLK; 1237 1238 cpuctrl = parse_cpu_options(args, sa110_options, cpuctrl); 1239 1240 /* Clear out the cache */ 1241 cpu_cache_purgeID(); 1242 1243 /* Set the control register */ 1244 /* cpu_control(cpuctrlmask, cpuctrl);*/ 1245 cpu_control(0xffffffff, cpuctrl); 1246 1247 /* enable clockswitching */ 1248 __asm ("mcr 15, 0, r0, c15, c1, 2"); 1249 } 1250 #endif /* CPU_SA110 */ 1251