1/* $NetBSD: cpufunc.c,v 1.65 2003/11/05 12:53:15 scw Exp $ */ 2 3/*- 4 * arm9 support code Copyright (C) 2001 ARM Ltd 5 * Copyright (c) 1997 Mark Brinicombe. 6 * Copyright (c) 1997 Causality Limited 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by Causality Limited. 20 * 4. The name of Causality Limited may not be used to endorse or promote 21 * products derived from this software without specific prior written 22 * permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS 25 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT, 28 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * RiscBSD kernel project 37 * 38 * cpufuncs.c 39 * 40 * C functions for supporting CPU / MMU / TLB specific operations. 41 * 42 * Created : 30/01/97 43 */ 44#include <sys/cdefs.h> 45__FBSDID("$FreeBSD: stable/11/sys/arm/arm/cpufunc.c 317003 2017-04-16 06:51:06Z mmel $"); 46 47#include <sys/param.h> 48#include <sys/systm.h> 49#include <sys/lock.h> 50#include <sys/mutex.h> 51#include <sys/bus.h> 52#include <machine/bus.h> 53#include <machine/cpu.h> 54#include <machine/disassem.h> 55 56#include <vm/vm.h> 57#include <vm/pmap.h> 58#include <vm/uma.h> 59 60#include <machine/cpufunc.h> 61 62#if defined(CPU_XSCALE_81342) 63#include <arm/xscale/i8134x/i81342reg.h> 64#endif 65 66#ifdef CPU_XSCALE_IXP425 67#include <arm/xscale/ixp425/ixp425reg.h> 68#include <arm/xscale/ixp425/ixp425var.h> 69#endif 70 71/* PRIMARY CACHE VARIABLES */ 72int arm_picache_size; 73int arm_picache_line_size; 74int arm_picache_ways; 75 76int arm_pdcache_size; /* and unified */ 77int arm_pdcache_line_size; 78int arm_pdcache_ways; 79 80int arm_pcache_type; 81int arm_pcache_unified; 82 83int arm_dcache_align; 84int arm_dcache_align_mask; 85 86u_int arm_cache_level; 87u_int arm_cache_type[14]; 88u_int arm_cache_loc; 89 90#ifdef CPU_ARM9 91struct cpu_functions arm9_cpufuncs = { 92 /* CPU functions */ 93 94 cpufunc_nullop, /* cpwait */ 95 96 /* MMU functions */ 97 98 cpufunc_control, /* control */ 99 arm9_setttb, /* Setttb */ 100 101 /* TLB functions */ 102 103 armv4_tlb_flushID, /* tlb_flushID */ 104 arm9_tlb_flushID_SE, /* tlb_flushID_SE */ 105 armv4_tlb_flushD, /* tlb_flushD */ 106 armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 107 108 /* Cache operations */ 109 110 arm9_icache_sync_range, /* icache_sync_range */ 111 112 arm9_dcache_wbinv_all, /* dcache_wbinv_all */ 113 arm9_dcache_wbinv_range, /* dcache_wbinv_range */ 114 arm9_dcache_inv_range, /* dcache_inv_range */ 115 arm9_dcache_wb_range, /* dcache_wb_range */ 116 117 armv4_idcache_inv_all, /* idcache_inv_all */ 118 arm9_idcache_wbinv_all, /* idcache_wbinv_all */ 119 arm9_idcache_wbinv_range, /* idcache_wbinv_range */ 120 cpufunc_nullop, /* l2cache_wbinv_all */ 121 (void *)cpufunc_nullop, /* l2cache_wbinv_range */ 122 (void *)cpufunc_nullop, /* l2cache_inv_range */ 123 (void *)cpufunc_nullop, /* l2cache_wb_range */ 124 (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 125 126 /* Other functions */ 127 128 armv4_drain_writebuf, /* drain_writebuf */ 129 130 (void *)cpufunc_nullop, /* sleep */ 131 132 /* Soft functions */ 133 134 arm9_context_switch, /* context_switch */ 135 136 arm9_setup /* cpu setup */ 137 138}; 139#endif /* CPU_ARM9 */ 140 141#if defined(CPU_ARM9E) 142struct cpu_functions armv5_ec_cpufuncs = { 143 /* CPU functions */ 144 145 cpufunc_nullop, /* cpwait */ 146 147 /* MMU functions */ 148 149 cpufunc_control, /* control */ 150 armv5_ec_setttb, /* Setttb */ 151 152 /* TLB functions */ 153 154 armv4_tlb_flushID, /* tlb_flushID */ 155 arm9_tlb_flushID_SE, /* tlb_flushID_SE */ 156 armv4_tlb_flushD, /* tlb_flushD */ 157 armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 158 159 /* Cache operations */ 160 161 armv5_ec_icache_sync_range, /* icache_sync_range */ 162 163 armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */ 164 armv5_ec_dcache_wbinv_range, /* dcache_wbinv_range */ 165 armv5_ec_dcache_inv_range, /* dcache_inv_range */ 166 armv5_ec_dcache_wb_range, /* dcache_wb_range */ 167 168 armv4_idcache_inv_all, /* idcache_inv_all */ 169 armv5_ec_idcache_wbinv_all, /* idcache_wbinv_all */ 170 armv5_ec_idcache_wbinv_range, /* idcache_wbinv_range */ 171 172 cpufunc_nullop, /* l2cache_wbinv_all */ 173 (void *)cpufunc_nullop, /* l2cache_wbinv_range */ 174 (void *)cpufunc_nullop, /* l2cache_inv_range */ 175 (void *)cpufunc_nullop, /* l2cache_wb_range */ 176 (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 177 178 /* Other functions */ 179 180 armv4_drain_writebuf, /* drain_writebuf */ 181 182 (void *)cpufunc_nullop, /* sleep */ 183 184 /* Soft functions */ 185 186 arm9_context_switch, /* context_switch */ 187 188 arm10_setup /* cpu setup */ 189 190}; 191 192struct cpu_functions sheeva_cpufuncs = { 193 /* CPU functions */ 194 195 cpufunc_nullop, /* cpwait */ 196 197 /* MMU functions */ 198 199 cpufunc_control, /* control */ 200 sheeva_setttb, /* Setttb */ 201 202 /* TLB functions */ 203 204 armv4_tlb_flushID, /* tlb_flushID */ 205 arm9_tlb_flushID_SE, /* tlb_flushID_SE */ 206 armv4_tlb_flushD, /* tlb_flushD */ 207 armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 208 209 /* Cache operations */ 210 211 armv5_ec_icache_sync_range, /* icache_sync_range */ 212 213 armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */ 214 sheeva_dcache_wbinv_range, /* dcache_wbinv_range */ 215 sheeva_dcache_inv_range, /* dcache_inv_range */ 216 sheeva_dcache_wb_range, /* dcache_wb_range */ 217 218 armv4_idcache_inv_all, /* idcache_inv_all */ 219 armv5_ec_idcache_wbinv_all, /* idcache_wbinv_all */ 220 sheeva_idcache_wbinv_range, /* idcache_wbinv_all */ 221 222 sheeva_l2cache_wbinv_all, /* l2cache_wbinv_all */ 223 sheeva_l2cache_wbinv_range, /* l2cache_wbinv_range */ 224 sheeva_l2cache_inv_range, /* l2cache_inv_range */ 225 sheeva_l2cache_wb_range, /* l2cache_wb_range */ 226 (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 227 228 /* Other functions */ 229 230 armv4_drain_writebuf, /* drain_writebuf */ 231 232 sheeva_cpu_sleep, /* sleep */ 233 234 /* Soft functions */ 235 236 arm9_context_switch, /* context_switch */ 237 238 arm10_setup /* cpu setup */ 239}; 240#endif /* CPU_ARM9E */ 241 242#ifdef CPU_MV_PJ4B 243struct cpu_functions pj4bv7_cpufuncs = { 244 245 /* Cache operations */ 246 .cf_l2cache_wbinv_all = (void *)cpufunc_nullop, 247 .cf_l2cache_wbinv_range = (void *)cpufunc_nullop, 248 .cf_l2cache_inv_range = (void *)cpufunc_nullop, 249 .cf_l2cache_wb_range = (void *)cpufunc_nullop, 250 .cf_l2cache_drain_writebuf = (void *)cpufunc_nullop, 251 252 /* Other functions */ 253 .cf_sleep = (void *)cpufunc_nullop, 254 255 /* Soft functions */ 256 .cf_setup = pj4bv7_setup 257}; 258#endif /* CPU_MV_PJ4B */ 259 260#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) 261 262struct cpu_functions xscale_cpufuncs = { 263 /* CPU functions */ 264 265 xscale_cpwait, /* cpwait */ 266 267 /* MMU functions */ 268 269 xscale_control, /* control */ 270 xscale_setttb, /* setttb */ 271 272 /* TLB functions */ 273 274 armv4_tlb_flushID, /* tlb_flushID */ 275 xscale_tlb_flushID_SE, /* tlb_flushID_SE */ 276 armv4_tlb_flushD, /* tlb_flushD */ 277 armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 278 279 /* Cache operations */ 280 281 xscale_cache_syncI_rng, /* icache_sync_range */ 282 283 xscale_cache_purgeD, /* dcache_wbinv_all */ 284 xscale_cache_purgeD_rng, /* dcache_wbinv_range */ 285 xscale_cache_flushD_rng, /* dcache_inv_range */ 286 xscale_cache_cleanD_rng, /* dcache_wb_range */ 287 288 xscale_cache_flushID, /* idcache_inv_all */ 289 xscale_cache_purgeID, /* idcache_wbinv_all */ 290 xscale_cache_purgeID_rng, /* idcache_wbinv_range */ 291 cpufunc_nullop, /* l2cache_wbinv_all */ 292 (void *)cpufunc_nullop, /* l2cache_wbinv_range */ 293 (void *)cpufunc_nullop, /* l2cache_inv_range */ 294 (void *)cpufunc_nullop, /* l2cache_wb_range */ 295 (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 296 297 /* Other functions */ 298 299 armv4_drain_writebuf, /* drain_writebuf */ 300 301 xscale_cpu_sleep, /* sleep */ 302 303 /* Soft functions */ 304 305 xscale_context_switch, /* context_switch */ 306 307 xscale_setup /* cpu setup */ 308}; 309#endif 310/* CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */ 311 312#ifdef CPU_XSCALE_81342 313struct cpu_functions xscalec3_cpufuncs = { 314 /* CPU functions */ 315 316 xscale_cpwait, /* cpwait */ 317 318 /* MMU functions */ 319 320 xscale_control, /* control */ 321 xscalec3_setttb, /* setttb */ 322 323 /* TLB functions */ 324 325 armv4_tlb_flushID, /* tlb_flushID */ 326 xscale_tlb_flushID_SE, /* tlb_flushID_SE */ 327 armv4_tlb_flushD, /* tlb_flushD */ 328 armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 329 330 /* Cache operations */ 331 332 xscalec3_cache_syncI_rng, /* icache_sync_range */ 333 334 xscalec3_cache_purgeD, /* dcache_wbinv_all */ 335 xscalec3_cache_purgeD_rng, /* dcache_wbinv_range */ 336 xscale_cache_flushD_rng, /* dcache_inv_range */ 337 xscalec3_cache_cleanD_rng, /* dcache_wb_range */ 338 339 xscale_cache_flushID, /* idcache_inv_all */ 340 xscalec3_cache_purgeID, /* idcache_wbinv_all */ 341 xscalec3_cache_purgeID_rng, /* idcache_wbinv_range */ 342 xscalec3_l2cache_purge, /* l2cache_wbinv_all */ 343 xscalec3_l2cache_purge_rng, /* l2cache_wbinv_range */ 344 xscalec3_l2cache_flush_rng, /* l2cache_inv_range */ 345 xscalec3_l2cache_clean_rng, /* l2cache_wb_range */ 346 (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 347 348 /* Other functions */ 349 350 armv4_drain_writebuf, /* drain_writebuf */ 351 352 xscale_cpu_sleep, /* sleep */ 353 354 /* Soft functions */ 355 356 xscalec3_context_switch, /* context_switch */ 357 358 xscale_setup /* cpu setup */ 359}; 360#endif /* CPU_XSCALE_81342 */ 361 362 363#if defined(CPU_FA526) 364struct cpu_functions fa526_cpufuncs = { 365 /* CPU functions */ 366 367 cpufunc_nullop, /* cpwait */ 368 369 /* MMU functions */ 370 371 cpufunc_control, /* control */ 372 fa526_setttb, /* setttb */ 373 374 /* TLB functions */ 375 376 armv4_tlb_flushID, /* tlb_flushID */ 377 fa526_tlb_flushID_SE, /* tlb_flushID_SE */ 378 armv4_tlb_flushD, /* tlb_flushD */ 379 armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 380 381 /* Cache operations */ 382 383 fa526_icache_sync_range, /* icache_sync_range */ 384 385 fa526_dcache_wbinv_all, /* dcache_wbinv_all */ 386 fa526_dcache_wbinv_range, /* dcache_wbinv_range */ 387 fa526_dcache_inv_range, /* dcache_inv_range */ 388 fa526_dcache_wb_range, /* dcache_wb_range */ 389 390 armv4_idcache_inv_all, /* idcache_inv_all */ 391 fa526_idcache_wbinv_all, /* idcache_wbinv_all */ 392 fa526_idcache_wbinv_range, /* idcache_wbinv_range */ 393 cpufunc_nullop, /* l2cache_wbinv_all */ 394 (void *)cpufunc_nullop, /* l2cache_wbinv_range */ 395 (void *)cpufunc_nullop, /* l2cache_inv_range */ 396 (void *)cpufunc_nullop, /* l2cache_wb_range */ 397 (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 398 399 /* Other functions */ 400 401 armv4_drain_writebuf, /* drain_writebuf */ 402 403 fa526_cpu_sleep, /* sleep */ 404 405 /* Soft functions */ 406 407 408 fa526_context_switch, /* context_switch */ 409 410 fa526_setup /* cpu setup */ 411}; 412#endif /* CPU_FA526 */ 413 414#if defined(CPU_ARM1176) 415struct cpu_functions arm1176_cpufuncs = { 416 417 /* Cache operations */ 418 .cf_l2cache_wbinv_all = (void *)cpufunc_nullop, 419 .cf_l2cache_wbinv_range = (void *)cpufunc_nullop, 420 .cf_l2cache_inv_range = (void *)cpufunc_nullop, 421 .cf_l2cache_wb_range = (void *)cpufunc_nullop, 422 .cf_l2cache_drain_writebuf = (void *)cpufunc_nullop, 423 424 /* Other functions */ 425 .cf_sleep = arm11x6_sleep, 426 427 /* Soft functions */ 428 .cf_setup = arm11x6_setup 429}; 430#endif /*CPU_ARM1176 */ 431 432#if defined(CPU_CORTEXA) || defined(CPU_KRAIT) 433struct cpu_functions cortexa_cpufuncs = { 434 435 /* Cache operations */ 436 437 /* 438 * Note: For CPUs using the PL310 the L2 ops are filled in when the 439 * L2 cache controller is actually enabled. 440 */ 441 .cf_l2cache_wbinv_all = cpufunc_nullop, 442 .cf_l2cache_wbinv_range = (void *)cpufunc_nullop, 443 .cf_l2cache_inv_range = (void *)cpufunc_nullop, 444 .cf_l2cache_wb_range = (void *)cpufunc_nullop, 445 .cf_l2cache_drain_writebuf = (void *)cpufunc_nullop, 446 447 /* Other functions */ 448 .cf_sleep = armv7_cpu_sleep, 449 450 /* Soft functions */ 451 .cf_setup = cortexa_setup 452}; 453#endif /* CPU_CORTEXA */ 454 455/* 456 * Global constants also used by locore.s 457 */ 458 459struct cpu_functions cpufuncs; 460u_int cputype; 461#if __ARM_ARCH <= 5 462u_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore-v4.s */ 463#endif 464 465#if defined(CPU_ARM9) || \ 466 defined (CPU_ARM9E) || \ 467 defined(CPU_ARM1176) || \ 468 defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ 469 defined(CPU_FA526) || defined(CPU_MV_PJ4B) || \ 470 defined(CPU_XSCALE_81342) || \ 471 defined(CPU_CORTEXA) || defined(CPU_KRAIT) 472 473/* Global cache line sizes, use 32 as default */ 474int arm_dcache_min_line_size = 32; 475int arm_icache_min_line_size = 32; 476int arm_idcache_min_line_size = 32; 477 478static void get_cachetype_cp15(void); 479 480/* Additional cache information local to this file. Log2 of some of the 481 above numbers. */ 482static int arm_dcache_l2_nsets; 483static int arm_dcache_l2_assoc; 484static int arm_dcache_l2_linesize; 485 486static void 487get_cachetype_cp15(void) 488{ 489 u_int ctype, isize, dsize, cpuid; 490 u_int clevel, csize, i, sel; 491 u_int multiplier; 492 u_char type; 493 494 __asm __volatile("mrc p15, 0, %0, c0, c0, 1" 495 : "=r" (ctype)); 496 497 cpuid = cpu_ident(); 498 /* 499 * ...and thus spake the ARM ARM: 500 * 501 * If an <opcode2> value corresponding to an unimplemented or 502 * reserved ID register is encountered, the System Control 503 * processor returns the value of the main ID register. 504 */ 505 if (ctype == cpuid) 506 goto out; 507 508 if (CPU_CT_FORMAT(ctype) == CPU_CT_ARMV7) { 509 /* Resolve minimal cache line sizes */ 510 arm_dcache_min_line_size = 1 << (CPU_CT_DMINLINE(ctype) + 2); 511 arm_icache_min_line_size = 1 << (CPU_CT_IMINLINE(ctype) + 2); 512 arm_idcache_min_line_size = 513 min(arm_icache_min_line_size, arm_dcache_min_line_size); 514 515 __asm __volatile("mrc p15, 1, %0, c0, c0, 1" 516 : "=r" (clevel)); 517 arm_cache_level = clevel; 518 arm_cache_loc = CPU_CLIDR_LOC(arm_cache_level); 519 i = 0; 520 while ((type = (clevel & 0x7)) && i < 7) { 521 if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE || 522 type == CACHE_SEP_CACHE) { 523 sel = i << 1; 524 __asm __volatile("mcr p15, 2, %0, c0, c0, 0" 525 : : "r" (sel)); 526 __asm __volatile("mrc p15, 1, %0, c0, c0, 0" 527 : "=r" (csize)); 528 arm_cache_type[sel] = csize; 529 arm_dcache_align = 1 << 530 (CPUV7_CT_xSIZE_LEN(csize) + 4); 531 arm_dcache_align_mask = arm_dcache_align - 1; 532 } 533 if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) { 534 sel = (i << 1) | 1; 535 __asm __volatile("mcr p15, 2, %0, c0, c0, 0" 536 : : "r" (sel)); 537 __asm __volatile("mrc p15, 1, %0, c0, c0, 0" 538 : "=r" (csize)); 539 arm_cache_type[sel] = csize; 540 } 541 i++; 542 clevel >>= 3; 543 } 544 } else { 545 if ((ctype & CPU_CT_S) == 0) 546 arm_pcache_unified = 1; 547 548 /* 549 * If you want to know how this code works, go read the ARM ARM. 550 */ 551 552 arm_pcache_type = CPU_CT_CTYPE(ctype); 553 554 if (arm_pcache_unified == 0) { 555 isize = CPU_CT_ISIZE(ctype); 556 multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2; 557 arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3); 558 if (CPU_CT_xSIZE_ASSOC(isize) == 0) { 559 if (isize & CPU_CT_xSIZE_M) 560 arm_picache_line_size = 0; /* not present */ 561 else 562 arm_picache_ways = 1; 563 } else { 564 arm_picache_ways = multiplier << 565 (CPU_CT_xSIZE_ASSOC(isize) - 1); 566 } 567 arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8); 568 } 569 570 dsize = CPU_CT_DSIZE(ctype); 571 multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2; 572 arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3); 573 if (CPU_CT_xSIZE_ASSOC(dsize) == 0) { 574 if (dsize & CPU_CT_xSIZE_M) 575 arm_pdcache_line_size = 0; /* not present */ 576 else 577 arm_pdcache_ways = 1; 578 } else { 579 arm_pdcache_ways = multiplier << 580 (CPU_CT_xSIZE_ASSOC(dsize) - 1); 581 } 582 arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8); 583 584 arm_dcache_align = arm_pdcache_line_size; 585 586 arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2; 587 arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3; 588 arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) - 589 CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize); 590 591 out: 592 arm_dcache_align_mask = arm_dcache_align - 1; 593 } 594} 595#endif /* ARM9 || XSCALE */ 596 597/* 598 * Cannot panic here as we may not have a console yet ... 599 */ 600 601int 602set_cpufuncs(void) 603{ 604 cputype = cpu_ident(); 605 cputype &= CPU_ID_CPU_MASK; 606 607#ifdef CPU_ARM9 608 if (((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD || 609 (cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_TI) && 610 (cputype & 0x0000f000) == 0x00009000) { 611 cpufuncs = arm9_cpufuncs; 612 cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */ 613 get_cachetype_cp15(); 614 arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize; 615 arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize + 616 arm_dcache_l2_nsets)) - arm9_dcache_sets_inc; 617 arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc); 618 arm9_dcache_index_max = 0U - arm9_dcache_index_inc; 619 pmap_pte_init_generic(); 620 goto out; 621 } 622#endif /* CPU_ARM9 */ 623#if defined(CPU_ARM9E) 624 if (cputype == CPU_ID_MV88FR131 || cputype == CPU_ID_MV88FR571_VD || 625 cputype == CPU_ID_MV88FR571_41) { 626 uint32_t sheeva_ctrl; 627 628 sheeva_ctrl = (MV_DC_STREAM_ENABLE | MV_BTB_DISABLE | 629 MV_L2_ENABLE); 630 /* 631 * Workaround for Marvell MV78100 CPU: Cache prefetch 632 * mechanism may affect the cache coherency validity, 633 * so it needs to be disabled. 634 * 635 * Refer to errata document MV-S501058-00C.pdf (p. 3.1 636 * L2 Prefetching Mechanism) for details. 637 */ 638 if (cputype == CPU_ID_MV88FR571_VD || 639 cputype == CPU_ID_MV88FR571_41) 640 sheeva_ctrl |= MV_L2_PREFETCH_DISABLE; 641 642 sheeva_control_ext(0xffffffff & ~MV_WA_ENABLE, sheeva_ctrl); 643 644 cpufuncs = sheeva_cpufuncs; 645 get_cachetype_cp15(); 646 pmap_pte_init_generic(); 647 goto out; 648 } else if (cputype == CPU_ID_ARM926EJS) { 649 cpufuncs = armv5_ec_cpufuncs; 650 get_cachetype_cp15(); 651 pmap_pte_init_generic(); 652 goto out; 653 } 654#endif /* CPU_ARM9E */ 655#if defined(CPU_ARM1176) 656 if (cputype == CPU_ID_ARM1176JZS) { 657 cpufuncs = arm1176_cpufuncs; 658 get_cachetype_cp15(); 659 goto out; 660 } 661#endif /* CPU_ARM1176 */ 662#if defined(CPU_CORTEXA) || defined(CPU_KRAIT) 663 switch(cputype & CPU_ID_SCHEME_MASK) { 664 case CPU_ID_CORTEXA5: 665 case CPU_ID_CORTEXA7: 666 case CPU_ID_CORTEXA8: 667 case CPU_ID_CORTEXA9: 668 case CPU_ID_CORTEXA12: 669 case CPU_ID_CORTEXA15: 670 case CPU_ID_CORTEXA53: 671 case CPU_ID_CORTEXA57: 672 case CPU_ID_CORTEXA72: 673 case CPU_ID_KRAIT300: 674 cpufuncs = cortexa_cpufuncs; 675 get_cachetype_cp15(); 676 goto out; 677 default: 678 break; 679 } 680#endif /* CPU_CORTEXA */ 681 682#if defined(CPU_MV_PJ4B) 683 if (cputype == CPU_ID_MV88SV581X_V7 || 684 cputype == CPU_ID_MV88SV584X_V7 || 685 cputype == CPU_ID_ARM_88SV581X_V7) { 686 cpufuncs = pj4bv7_cpufuncs; 687 get_cachetype_cp15(); 688 goto out; 689 } 690#endif /* CPU_MV_PJ4B */ 691 692#if defined(CPU_FA526) 693 if (cputype == CPU_ID_FA526 || cputype == CPU_ID_FA626TE) { 694 cpufuncs = fa526_cpufuncs; 695 cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */ 696 get_cachetype_cp15(); 697 pmap_pte_init_generic(); 698 699 goto out; 700 } 701#endif /* CPU_FA526 */ 702 703#if defined(CPU_XSCALE_81342) 704 if (cputype == CPU_ID_81342) { 705 cpufuncs = xscalec3_cpufuncs; 706 cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 707 get_cachetype_cp15(); 708 pmap_pte_init_xscale(); 709 goto out; 710 } 711#endif /* CPU_XSCALE_81342 */ 712#ifdef CPU_XSCALE_PXA2X0 713 /* ignore core revision to test PXA2xx CPUs */ 714 if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA250 || 715 (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X || 716 (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA210) { 717 718 cpufuncs = xscale_cpufuncs; 719 cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 720 get_cachetype_cp15(); 721 pmap_pte_init_xscale(); 722 723 goto out; 724 } 725#endif /* CPU_XSCALE_PXA2X0 */ 726#ifdef CPU_XSCALE_IXP425 727 if (cputype == CPU_ID_IXP425_533 || cputype == CPU_ID_IXP425_400 || 728 cputype == CPU_ID_IXP425_266 || cputype == CPU_ID_IXP435) { 729 730 cpufuncs = xscale_cpufuncs; 731 cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 732 get_cachetype_cp15(); 733 pmap_pte_init_xscale(); 734 735 goto out; 736 } 737#endif /* CPU_XSCALE_IXP425 */ 738 /* 739 * Bzzzz. And the answer was ... 740 */ 741 panic("No support for this CPU type (%08x) in kernel", cputype); 742 return(ARCHITECTURE_NOT_PRESENT); 743out: 744 uma_set_align(arm_dcache_align_mask); 745 return (0); 746} 747 748/* 749 * CPU Setup code 750 */ 751 752#ifdef CPU_ARM9 753void 754arm9_setup(void) 755{ 756 int cpuctrl, cpuctrlmask; 757 758 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 759 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 760 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 761 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE | 762 CPU_CONTROL_ROUNDROBIN; 763 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 764 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 765 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 766 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 767 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 768 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_VECRELOC 769 | CPU_CONTROL_ROUNDROBIN; 770 771#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 772 cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 773#endif 774 775#ifdef __ARMEB__ 776 cpuctrl |= CPU_CONTROL_BEND_ENABLE; 777#endif 778 if (vector_page == ARM_VECTORS_HIGH) 779 cpuctrl |= CPU_CONTROL_VECRELOC; 780 781 /* Clear out the cache */ 782 cpu_idcache_wbinv_all(); 783 784 /* Set the control register (SCTLR) */ 785 cpu_control(cpuctrlmask, cpuctrl); 786 787} 788#endif /* CPU_ARM9 */ 789 790#if defined(CPU_ARM9E) 791void 792arm10_setup(void) 793{ 794 int cpuctrl, cpuctrlmask; 795 796 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE 797 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 798 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE; 799 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE 800 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 801 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 802 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 803 | CPU_CONTROL_BPRD_ENABLE 804 | CPU_CONTROL_ROUNDROBIN | CPU_CONTROL_CPCLK; 805 806#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 807 cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 808#endif 809 810#ifdef __ARMEB__ 811 cpuctrl |= CPU_CONTROL_BEND_ENABLE; 812#endif 813 814 /* Clear out the cache */ 815 cpu_idcache_wbinv_all(); 816 817 /* Now really make sure they are clean. */ 818 __asm __volatile ("mcr\tp15, 0, r0, c7, c7, 0" : : ); 819 820 if (vector_page == ARM_VECTORS_HIGH) 821 cpuctrl |= CPU_CONTROL_VECRELOC; 822 823 /* Set the control register */ 824 cpu_control(0xffffffff, cpuctrl); 825 826 /* And again. */ 827 cpu_idcache_wbinv_all(); 828} 829#endif /* CPU_ARM9E || CPU_ARM10 */ 830 831#if defined(CPU_ARM1176) \ 832 || defined(CPU_MV_PJ4B) \ 833 || defined(CPU_CORTEXA) || defined(CPU_KRAIT) 834static __inline void 835cpu_scc_setup_ccnt(void) 836{ 837/* This is how you give userland access to the CCNT and PMCn 838 * registers. 839 * BEWARE! This gives write access also, which may not be what 840 * you want! 841 */ 842#ifdef _PMC_USER_READ_WRITE_ 843 /* Set PMUSERENR[0] to allow userland access */ 844 cp15_pmuserenr_set(1); 845#endif 846#if defined(CPU_ARM1176) 847 /* Set PMCR[2,0] to enable counters and reset CCNT */ 848 cp15_pmcr_set(5); 849#else 850 /* Set up the PMCCNTR register as a cyclecounter: 851 * Set PMINTENCLR to 0xFFFFFFFF to block interrupts 852 * Set PMCR[2,0] to enable counters and reset CCNT 853 * Set PMCNTENSET to 0x80000000 to enable CCNT */ 854 cp15_pminten_clr(0xFFFFFFFF); 855 cp15_pmcr_set(5); 856 cp15_pmcnten_set(0x80000000); 857#endif 858} 859#endif 860 861#if defined(CPU_ARM1176) 862void 863arm11x6_setup(void) 864{ 865 uint32_t auxctrl, auxctrl_wax; 866 uint32_t tmp, tmp2; 867 uint32_t cpuid; 868 869 cpuid = cpu_ident(); 870 871 auxctrl = 0; 872 auxctrl_wax = ~0; 873 874 /* 875 * Enable an errata workaround 876 */ 877 if ((cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM1176JZS) { /* ARM1176JZSr0 */ 878 auxctrl = ARM1176_AUXCTL_PHD; 879 auxctrl_wax = ~ARM1176_AUXCTL_PHD; 880 } 881 882 tmp = cp15_actlr_get(); 883 tmp2 = tmp; 884 tmp &= auxctrl_wax; 885 tmp |= auxctrl; 886 if (tmp != tmp2) 887 cp15_actlr_set(tmp); 888 889 cpu_scc_setup_ccnt(); 890} 891#endif /* CPU_ARM1176 */ 892 893#ifdef CPU_MV_PJ4B 894void 895pj4bv7_setup(void) 896{ 897 898 pj4b_config(); 899 cpu_scc_setup_ccnt(); 900} 901#endif /* CPU_MV_PJ4B */ 902 903#if defined(CPU_CORTEXA) || defined(CPU_KRAIT) 904 905void 906cortexa_setup(void) 907{ 908 909 cpu_scc_setup_ccnt(); 910} 911#endif /* CPU_CORTEXA */ 912 913#if defined(CPU_FA526) 914void 915fa526_setup(void) 916{ 917 int cpuctrl, cpuctrlmask; 918 919 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 920 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 921 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 922 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE 923 | CPU_CONTROL_BPRD_ENABLE; 924 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 925 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 926 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 927 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 928 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 929 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE 930 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC; 931 932#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 933 cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 934#endif 935 936#ifdef __ARMEB__ 937 cpuctrl |= CPU_CONTROL_BEND_ENABLE; 938#endif 939 940 if (vector_page == ARM_VECTORS_HIGH) 941 cpuctrl |= CPU_CONTROL_VECRELOC; 942 943 /* Clear out the cache */ 944 cpu_idcache_wbinv_all(); 945 946 /* Set the control register */ 947 cpu_control(0xffffffff, cpuctrl); 948} 949#endif /* CPU_FA526 */ 950 951#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ 952 defined(CPU_XSCALE_81342) 953void 954xscale_setup(void) 955{ 956 uint32_t auxctl; 957 int cpuctrl, cpuctrlmask; 958 959 /* 960 * The XScale Write Buffer is always enabled. Our option 961 * is to enable/disable coalescing. Note that bits 6:3 962 * must always be enabled. 963 */ 964 965 cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 966 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 967 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 968 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE 969 | CPU_CONTROL_BPRD_ENABLE; 970 cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 971 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 972 | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 973 | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 974 | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 975 | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE 976 | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC | \ 977 CPU_CONTROL_L2_ENABLE; 978 979#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 980 cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 981#endif 982 983#ifdef __ARMEB__ 984 cpuctrl |= CPU_CONTROL_BEND_ENABLE; 985#endif 986 987 if (vector_page == ARM_VECTORS_HIGH) 988 cpuctrl |= CPU_CONTROL_VECRELOC; 989#ifdef CPU_XSCALE_CORE3 990 cpuctrl |= CPU_CONTROL_L2_ENABLE; 991#endif 992 993 /* Clear out the cache */ 994 cpu_idcache_wbinv_all(); 995 996 /* 997 * Set the control register. Note that bits 6:3 must always 998 * be set to 1. 999 */ 1000/* cpu_control(cpuctrlmask, cpuctrl);*/ 1001 cpu_control(0xffffffff, cpuctrl); 1002 1003 /* Make sure write coalescing is turned on */ 1004 __asm __volatile("mrc p15, 0, %0, c1, c0, 1" 1005 : "=r" (auxctl)); 1006#ifdef XSCALE_NO_COALESCE_WRITES 1007 auxctl |= XSCALE_AUXCTL_K; 1008#else 1009 auxctl &= ~XSCALE_AUXCTL_K; 1010#endif 1011#ifdef CPU_XSCALE_CORE3 1012 auxctl |= XSCALE_AUXCTL_LLR; 1013 auxctl |= XSCALE_AUXCTL_MD_MASK; 1014#endif 1015 __asm __volatile("mcr p15, 0, %0, c1, c0, 1" 1016 : : "r" (auxctl)); 1017} 1018#endif /* CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */ 1019