1 /* $OpenBSD: cpu.c,v 1.90 2024/10/24 17:37:06 gkoehler Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Per Fogelstrom 5 * Copyright (c) 1997 RTMX Inc 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed under OpenBSD for RTMX Inc 18 * North Carolina, USA, by Per Fogelstrom, Opsycon AB, Sweden. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 23 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 26 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/proc.h> 39 #include <sys/sysctl.h> 40 #include <sys/task.h> 41 #include <sys/device.h> 42 43 #include <uvm/uvm_extern.h> 44 45 #include <dev/ofw/openfirm.h> 46 47 #include <machine/autoconf.h> 48 #include <powerpc/bat.h> 49 #include <machine/cpu.h> 50 #include <machine/trap.h> 51 #include <machine/elf.h> 52 #include <powerpc/hid.h> 53 54 /* SCOM addresses (24-bit) */ 55 #define SCOM_PCR 0x0aa001 /* Power Control Register */ 56 #define SCOM_PSR 0x408001 /* Power Tuning Status Register */ 57 58 /* SCOMC format */ 59 #define SCOMC_ADDR_SHIFT 8 60 #define SCOMC_ADDR_MASK 0xffff0000 61 #define SCOMC_READ 0x00008000 62 63 /* Power (Tuning) Status Register */ 64 #define PSR_CMD_RECEIVED 0x2000000000000000LL 65 #define PSR_CMD_COMPLETED 0x1000000000000000LL 66 #define PSR_FREQ_MASK 0x0300000000000000LL 67 #define PSR_FREQ_HALF 0x0100000000000000LL 68 69 struct cpu_info cpu_info[PPC_MAXPROCS]; 70 71 char cpu_model[80]; 72 char machine[] = MACHINE; /* cpu architecture */ 73 74 /* Definition of the driver for autoconfig. */ 75 int cpumatch(struct device *, void *, void *); 76 void cpuattach(struct device *, struct device *, void *); 77 78 const struct cfattach cpu_ca = { 79 sizeof(struct device), cpumatch, cpuattach 80 }; 81 82 struct cfdriver cpu_cd = { 83 NULL, "cpu", DV_DULL 84 }; 85 86 void ppc64_scale_frequency(u_int); 87 void (*ppc64_slew_voltage)(u_int); 88 void ppc64_setperf(int); 89 90 void config_l2cr(int); 91 92 int 93 cpumatch(struct device *parent, void *cfdata, void *aux) 94 { 95 struct confargs *ca = aux; 96 int *reg = ca->ca_reg; 97 98 /* make sure that we're looking for a CPU. */ 99 if (strcmp(ca->ca_name, cpu_cd.cd_name) != 0) 100 return (0); 101 102 if (reg[0] >= PPC_MAXPROCS) 103 return (0); 104 105 return (1); 106 } 107 108 u_int32_t ppc_curfreq; 109 u_int32_t ppc_maxfreq; 110 111 int 112 ppc_cpuspeed(int *freq) 113 { 114 *freq = ppc_curfreq; 115 116 return (0); 117 } 118 119 static u_int32_t ppc_power_mode_data[2]; 120 121 void 122 ppc64_scale_frequency(u_int freq_scale) 123 { 124 u_int64_t psr; 125 int s; 126 127 s = ppc_intr_disable(); 128 129 /* Clear PCRH and PCR. */ 130 ppc_mtscomd(0x00000000); 131 ppc_mtscomc(SCOM_PCR << SCOMC_ADDR_SHIFT); 132 ppc_mtscomd(0x80000000); 133 ppc_mtscomc(SCOM_PCR << SCOMC_ADDR_SHIFT); 134 135 /* Set PCR. */ 136 ppc_mtscomd(ppc_power_mode_data[freq_scale] | 0x80000000); 137 ppc_mtscomc(SCOM_PCR << SCOMC_ADDR_SHIFT); 138 139 /* Wait until frequency change is completed. */ 140 do { 141 ppc64_mtscomc((SCOM_PSR << SCOMC_ADDR_SHIFT) | SCOMC_READ); 142 psr = ppc64_mfscomd(); 143 ppc64_mfscomc(); 144 if (psr & PSR_CMD_COMPLETED) 145 break; 146 DELAY(100); 147 } while (psr & PSR_CMD_RECEIVED); 148 149 if ((psr & PSR_FREQ_MASK) == PSR_FREQ_HALF) 150 ppc_curfreq = ppc_maxfreq / 2; 151 else 152 ppc_curfreq = ppc_maxfreq; 153 154 ppc_intr_enable(s); 155 } 156 157 extern int perflevel; 158 159 struct task ppc64_setperf_task; 160 int ppc64_perflevel; 161 162 void 163 ppc64_do_setperf(void *arg) 164 { 165 if (ppc64_perflevel <= 50) { 166 if (ppc_curfreq == ppc_maxfreq / 2) 167 return; 168 169 ppc64_scale_frequency(FREQ_HALF); 170 if (ppc64_slew_voltage) 171 ppc64_slew_voltage(FREQ_HALF); 172 } else { 173 if (ppc_curfreq == ppc_maxfreq) 174 return; 175 176 if (ppc64_slew_voltage) 177 ppc64_slew_voltage(FREQ_FULL); 178 ppc64_scale_frequency(FREQ_FULL); 179 } 180 } 181 182 void 183 ppc64_setperf(int level) 184 { 185 ppc64_perflevel = level; 186 task_add(systq, &ppc64_setperf_task); 187 } 188 189 void 190 cpuattach(struct device *parent, struct device *dev, void *aux) 191 { 192 struct confargs *ca = aux; 193 int *reg = ca->ca_reg; 194 u_int32_t cpu, pvr, hid0; 195 char name[32]; 196 int qhandle, phandle, len; 197 u_int32_t clock_freq = 0, timebase = 0; 198 struct cpu_info *ci; 199 200 ci = &cpu_info[reg[0]]; 201 ci->ci_cpuid = reg[0]; 202 ci->ci_dev = dev; 203 204 hwcap = PPC_FEATURE_32 | PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_MMU; 205 206 pvr = ppc_mfpvr(); 207 cpu = pvr >> 16; 208 switch (cpu) { 209 case PPC_CPU_MPC601: 210 snprintf(cpu_model, sizeof(cpu_model), "601"); 211 break; 212 case PPC_CPU_MPC603: 213 snprintf(cpu_model, sizeof(cpu_model), "603"); 214 break; 215 case PPC_CPU_MPC604: 216 snprintf(cpu_model, sizeof(cpu_model), "604"); 217 break; 218 case PPC_CPU_MPC603e: 219 snprintf(cpu_model, sizeof(cpu_model), "603e"); 220 break; 221 case PPC_CPU_MPC603ev: 222 snprintf(cpu_model, sizeof(cpu_model), "603ev"); 223 break; 224 case PPC_CPU_MPC750: 225 snprintf(cpu_model, sizeof(cpu_model), "750"); 226 break; 227 case PPC_CPU_MPC604ev: 228 snprintf(cpu_model, sizeof(cpu_model), "604ev"); 229 break; 230 case PPC_CPU_MPC7400: 231 ppc_altivec = 1; 232 snprintf(cpu_model, sizeof(cpu_model), "7400"); 233 break; 234 case PPC_CPU_MPC7447A: 235 ppc_altivec = 1; 236 snprintf(cpu_model, sizeof(cpu_model), "7447A"); 237 break; 238 case PPC_CPU_MPC7448: 239 ppc_altivec = 1; 240 snprintf(cpu_model, sizeof(cpu_model), "7448"); 241 break; 242 case PPC_CPU_IBM970: 243 ppc_altivec = 1; 244 snprintf(cpu_model, sizeof(cpu_model), "970"); 245 break; 246 case PPC_CPU_IBM970FX: 247 ppc_altivec = 1; 248 snprintf(cpu_model, sizeof(cpu_model), "970FX"); 249 break; 250 case PPC_CPU_IBM970MP: 251 ppc_altivec = 1; 252 snprintf(cpu_model, sizeof(cpu_model), "970MP"); 253 break; 254 case PPC_CPU_IBM750FX: 255 snprintf(cpu_model, sizeof(cpu_model), "750FX"); 256 break; 257 case PPC_CPU_MPC7410: 258 ppc_altivec = 1; 259 snprintf(cpu_model, sizeof(cpu_model), "7410"); 260 break; 261 case PPC_CPU_MPC7450: 262 ppc_altivec = 1; 263 if ((pvr & 0xf) < 3) 264 snprintf(cpu_model, sizeof(cpu_model), "7450"); 265 else 266 snprintf(cpu_model, sizeof(cpu_model), "7451"); 267 break; 268 case PPC_CPU_MPC7455: 269 ppc_altivec = 1; 270 snprintf(cpu_model, sizeof(cpu_model), "7455"); 271 break; 272 case PPC_CPU_MPC7457: 273 ppc_altivec = 1; 274 snprintf(cpu_model, sizeof(cpu_model), "7457"); 275 break; 276 default: 277 snprintf(cpu_model, sizeof(cpu_model), "Version %x", cpu); 278 break; 279 } 280 #ifndef ALTIVEC /* altivec support absent from kernel */ 281 ppc_altivec = 0; 282 #endif 283 if (ppc_altivec) 284 hwcap |= PPC_FEATURE_HAS_ALTIVEC; 285 286 snprintf(cpu_model + strlen(cpu_model), 287 sizeof(cpu_model) - strlen(cpu_model), 288 " (Revision 0x%x)", pvr & 0xffff); 289 printf(": %s", cpu_model); 290 291 for (qhandle = OF_peer(0); qhandle; qhandle = phandle) { 292 len = OF_getprop(qhandle, "device_type", name, sizeof(name)); 293 if (len >= 0 && strcmp(name, "cpu") == 0) { 294 OF_getprop(qhandle, "clock-frequency", &clock_freq, 295 sizeof(clock_freq)); 296 OF_getprop(qhandle, "timebase-frequency", &timebase, 297 sizeof(timebase)); 298 break; 299 } 300 if ((phandle = OF_child(qhandle))) 301 continue; 302 while (qhandle) { 303 if ((phandle = OF_peer(qhandle))) 304 break; 305 qhandle = OF_parent(qhandle); 306 } 307 } 308 309 if (timebase != 0) { 310 ticks_per_sec = timebase; 311 ns_per_tick = 1000000000 / ticks_per_sec; 312 } 313 314 315 if (clock_freq != 0) { 316 /* Openfirmware stores clock in Hz, not MHz */ 317 clock_freq /= 1000000; 318 printf(": %d MHz", clock_freq); 319 ppc_curfreq = ppc_maxfreq = clock_freq; 320 cpu_cpuspeed = ppc_cpuspeed; 321 } 322 323 if (cpu == PPC_CPU_IBM970FX) { 324 u_int64_t psr; 325 int s; 326 327 s = ppc_intr_disable(); 328 ppc64_mtscomc((SCOM_PSR << SCOMC_ADDR_SHIFT) | SCOMC_READ); 329 psr = ppc64_mfscomd(); 330 ppc64_mfscomc(); 331 ppc_intr_enable(s); 332 333 if ((psr & PSR_FREQ_MASK) == PSR_FREQ_HALF) { 334 ppc_curfreq = ppc_maxfreq / 2; 335 perflevel = 50; 336 } 337 338 if (OF_getprop(qhandle, "power-mode-data", 339 &ppc_power_mode_data, sizeof ppc_power_mode_data) >= 8) { 340 task_set(&ppc64_setperf_task, ppc64_do_setperf, NULL); 341 cpu_setperf = ppc64_setperf; 342 } 343 } 344 345 /* power savings mode */ 346 hid0 = ppc_mfhid0(); 347 348 switch (cpu) { 349 case PPC_CPU_MPC603: 350 case PPC_CPU_MPC603e: 351 case PPC_CPU_MPC750: 352 case PPC_CPU_MPC7400: 353 case PPC_CPU_IBM750FX: 354 case PPC_CPU_MPC7410: 355 /* select DOZE mode */ 356 hid0 &= ~(HID0_NAP | HID0_SLEEP); 357 hid0 |= HID0_DOZE | HID0_DPM; 358 ppc_cpuidle = 1; 359 break; 360 case PPC_CPU_MPC7447A: 361 case PPC_CPU_MPC7448: 362 case PPC_CPU_MPC7450: 363 case PPC_CPU_MPC7455: 364 case PPC_CPU_MPC7457: 365 /* select NAP mode */ 366 hid0 &= ~(HID0_DOZE | HID0_SLEEP); 367 hid0 |= HID0_NAP | HID0_DPM; 368 /* try some other flags */ 369 hid0 |= HID0_SGE | HID0_BTIC; 370 hid0 |= HID0_LRSTK | HID0_FOLD | HID0_BHT; 371 /* Disable BTIC on 7450 Rev 2.0 or earlier */ 372 if (cpu == PPC_CPU_MPC7450 && (pvr & 0xffff) < 0x0200) 373 hid0 &= ~HID0_BTIC; 374 ppc_cpuidle = 1; 375 break; 376 case PPC_CPU_IBM970: 377 case PPC_CPU_IBM970FX: 378 /* select NAP mode */ 379 hid0 &= ~(HID0_DOZE | HID0_DEEPNAP); 380 hid0 |= HID0_NAP | HID0_DPM; 381 ppc_cpuidle = 1; 382 break; 383 case PPC_CPU_IBM970MP: 384 /* select DEEPNAP mode, which requires NAP */ 385 hid0 &= ~HID0_DOZE; 386 hid0 |= HID0_DEEPNAP | HID0_NAP | HID0_DPM; 387 ppc_cpuidle = 1; 388 break; 389 } 390 ppc_mthid0(hid0); 391 392 /* if processor is G3 or G4, configure L2 cache */ 393 switch (cpu) { 394 case PPC_CPU_MPC750: 395 case PPC_CPU_MPC7400: 396 case PPC_CPU_IBM750FX: 397 case PPC_CPU_MPC7410: 398 case PPC_CPU_MPC7447A: 399 case PPC_CPU_MPC7448: 400 case PPC_CPU_MPC7450: 401 case PPC_CPU_MPC7455: 402 case PPC_CPU_MPC7457: 403 config_l2cr(cpu); 404 break; 405 } 406 printf("\n"); 407 } 408 409 /* L2CR bit definitions */ 410 #define L2CR_L2E 0x80000000 /* 0: L2 enable */ 411 #define L2CR_L2PE 0x40000000 /* 1: L2 data parity enable */ 412 #define L2CR_L2SIZ 0x30000000 /* 2-3: L2 size */ 413 #define L2SIZ_RESERVED 0x00000000 414 #define L2SIZ_256K 0x10000000 415 #define L2SIZ_512K 0x20000000 416 #define L2SIZ_1M 0x30000000 417 #define L2CR_L2CLK 0x0e000000 /* 4-6: L2 clock ratio */ 418 #define L2CLK_DIS 0x00000000 /* disable L2 clock */ 419 #define L2CLK_10 0x02000000 /* core clock / 1 */ 420 #define L2CLK_15 0x04000000 /* / 1.5 */ 421 #define L2CLK_20 0x08000000 /* / 2 */ 422 #define L2CLK_25 0x0a000000 /* / 2.5 */ 423 #define L2CLK_30 0x0c000000 /* / 3 */ 424 #define L2CR_L2RAM 0x01800000 /* 7-8: L2 RAM type */ 425 #define L2RAM_FLOWTHRU_BURST 0x00000000 426 #define L2RAM_PIPELINE_BURST 0x01000000 427 #define L2RAM_PIPELINE_LATE 0x01800000 428 #define L2CR_L2DO 0x00400000 /* 9: L2 data-only. 429 Setting this bit disables instruction 430 caching. */ 431 #define L2CR_L2I 0x00200000 /* 10: L2 global invalidate. */ 432 #define L2CR_L2CTL 0x00100000 /* 11: L2 RAM control (ZZ enable). 433 Enables automatic operation of the 434 L2ZZ (low-power mode) signal. */ 435 #define L2CR_L2WT 0x00080000 /* 12: L2 write-through. */ 436 #define L2CR_L2TS 0x00040000 /* 13: L2 test support. */ 437 #define L2CR_L2OH 0x00030000 /* 14-15: L2 output hold. */ 438 #define L2CR_L2SL 0x00008000 /* 16: L2 DLL slow. */ 439 #define L2CR_L2DF 0x00004000 /* 17: L2 differential clock. */ 440 #define L2CR_L2BYP 0x00002000 /* 18: L2 DLL bypass. */ 441 #define L2CR_L2IP 0x00000001 /* 31: L2 global invalidate in progress 442 (read only). */ 443 #ifdef L2CR_CONFIG 444 u_int l2cr_config = L2CR_CONFIG; 445 #else 446 u_int l2cr_config = 0; 447 #endif 448 449 /* L3CR bit definitions */ 450 #define L3CR_L3E 0x80000000 /* 0: L3 enable */ 451 #define L3CR_L3SIZ 0x10000000 /* 3: L3 size (0=1MB, 1=2MB) */ 452 453 void 454 config_l2cr(int cpu) 455 { 456 u_int l2cr, x; 457 458 l2cr = ppc_mfl2cr(); 459 460 /* 461 * Configure L2 cache if not enabled. 462 */ 463 if ((l2cr & L2CR_L2E) == 0 && l2cr_config != 0) { 464 l2cr = l2cr_config; 465 ppc_mtl2cr(l2cr); 466 467 /* Wait for L2 clock to be stable (640 L2 clocks). */ 468 delay(100); 469 470 /* Invalidate all L2 contents. */ 471 l2cr |= L2CR_L2I; 472 ppc_mtl2cr(l2cr); 473 do { 474 x = ppc_mfl2cr(); 475 } while (x & L2CR_L2IP); 476 477 /* Enable L2 cache. */ 478 l2cr &= ~L2CR_L2I; 479 l2cr |= L2CR_L2E; 480 ppc_mtl2cr(l2cr); 481 } 482 483 if (l2cr & L2CR_L2E) { 484 if (cpu == PPC_CPU_MPC7450 || cpu == PPC_CPU_MPC7455) { 485 u_int l3cr; 486 487 printf(": 256KB L2 cache"); 488 489 l3cr = ppc_mfl3cr(); 490 if (l3cr & L3CR_L3E) 491 printf(", %cMB L3 cache", 492 l3cr & L3CR_L3SIZ ? '2' : '1'); 493 } else if (cpu == PPC_CPU_IBM750FX || 494 cpu == PPC_CPU_MPC7447A || cpu == PPC_CPU_MPC7457) 495 printf(": 512KB L2 cache"); 496 else if (cpu == PPC_CPU_MPC7448) 497 printf(": 1MB L2 cache"); 498 else { 499 switch (l2cr & L2CR_L2SIZ) { 500 case L2SIZ_256K: 501 printf(": 256KB"); 502 break; 503 case L2SIZ_512K: 504 printf(": 512KB"); 505 break; 506 case L2SIZ_1M: 507 printf(": 1MB"); 508 break; 509 default: 510 printf(": unknown size"); 511 } 512 printf(" backside cache"); 513 } 514 #if 0 515 switch (l2cr & L2CR_L2RAM) { 516 case L2RAM_FLOWTHRU_BURST: 517 printf(" Flow-through synchronous burst SRAM"); 518 break; 519 case L2RAM_PIPELINE_BURST: 520 printf(" Pipelined synchronous burst SRAM"); 521 break; 522 case L2RAM_PIPELINE_LATE: 523 printf(" Pipelined synchronous late-write SRAM"); 524 break; 525 default: 526 printf(" unknown type"); 527 } 528 529 if (l2cr & L2CR_L2PE) 530 printf(" with parity"); 531 #endif 532 } else 533 printf(": L2 cache not enabled"); 534 } 535 536 #ifdef MULTIPROCESSOR 537 538 #define INTSTK (8*1024) /* 8K interrupt stack */ 539 540 int cpu_spinup(struct device *, struct cpu_info *); 541 void cpu_hatch(void); 542 void cpu_spinup_trampoline(void); 543 544 struct cpu_hatch_data { 545 uint64_t tb; 546 struct cpu_info *ci; 547 uint32_t hid0; 548 uint64_t hid1; 549 uint64_t hid4; 550 uint64_t hid5; 551 int l2cr; 552 int running; 553 }; 554 555 volatile struct cpu_hatch_data *cpu_hatch_data; 556 volatile void *cpu_hatch_stack; 557 558 /* 559 * XXX Due to a bug in our OpenFirmware interface/memory mapping, 560 * machines with 64bit CPUs hang in the OF_finddevice() call below 561 * if this array is stored on the stack. 562 */ 563 char cpuname[64]; 564 565 int 566 cpu_spinup(struct device *self, struct cpu_info *ci) 567 { 568 volatile struct cpu_hatch_data hatch_data, *h = &hatch_data; 569 int i; 570 struct pglist mlist; 571 struct vm_page *m; 572 int error; 573 int size = 0; 574 char *cp; 575 u_char *reset_cpu; 576 u_int node; 577 578 /* 579 * Allocate some contiguous pages for the interrupt stack 580 * from the lowest 256MB (because bat0 always maps it va == pa). 581 */ 582 size += INTSTK; 583 size += 8192; /* SPILLSTK(1k) + DDBSTK(7k) */ 584 585 TAILQ_INIT(&mlist); 586 error = uvm_pglistalloc(size, 0x0, 0x10000000 - 1, 0, 0, 587 &mlist, 1, UVM_PLA_WAITOK); 588 if (error) { 589 printf(": unable to allocate idle stack\n"); 590 return -1; 591 } 592 593 m = TAILQ_FIRST(&mlist); 594 cp = (char *)VM_PAGE_TO_PHYS(m); 595 bzero(cp, size); 596 597 ci->ci_intstk = cp + INTSTK; 598 cpu_hatch_stack = ci->ci_intstk - sizeof(struct trapframe); 599 600 h->ci = ci; 601 h->running = 0; 602 h->hid0 = ppc_mfhid0(); 603 if (ppc_proc_is_64b) { 604 h->hid1 = ppc64_mfhid1(); 605 h->hid4 = ppc64_mfhid4(); 606 h->hid5 = ppc64_mfhid5(); 607 } else { 608 h->l2cr = ppc_mfl2cr(); 609 } 610 cpu_hatch_data = h; 611 612 __asm volatile ("sync; isync"); 613 614 /* XXX OpenPIC */ 615 { 616 int off; 617 618 *(u_int *)EXC_RST = 0x48000002 | (u_int)cpu_spinup_trampoline; 619 syncicache((void *)EXC_RST, 0x100); 620 621 h->running = -1; 622 623 snprintf(cpuname, sizeof(cpuname), "/cpus/@%x", ci->ci_cpuid); 624 node = OF_finddevice(cpuname); 625 if (node == -1) { 626 printf(": unable to locate OF node %s\n", cpuname); 627 return -1; 628 } 629 if (OF_getprop(node, "soft-reset", &off, 4) == 4) { 630 reset_cpu = mapiodev(0x80000000 + off, 1); 631 *reset_cpu = 0x4; 632 __asm volatile ("eieio" ::: "memory"); 633 *reset_cpu = 0x0; 634 __asm volatile ("eieio" ::: "memory"); 635 } else { 636 /* Start secondary CPU. */ 637 reset_cpu = mapiodev(0x80000000 + 0x5c, 1); 638 *reset_cpu = 0x4; 639 __asm volatile ("eieio" ::: "memory"); 640 *reset_cpu = 0x0; 641 __asm volatile ("eieio" ::: "memory"); 642 } 643 644 /* Sync timebase. */ 645 h->tb = ppc_mftb() + 100000; /* 3ms @ 33MHz */ 646 647 while (h->tb > ppc_mftb()) 648 ; 649 __asm volatile ("sync; isync"); 650 h->running = 0; 651 652 delay(500000); 653 } 654 655 656 for (i = 0; i < 0x3fffffff; i++) 657 if (h->running) { 658 break; 659 } 660 661 return 0; 662 } 663 664 volatile static int start_secondary_cpu; 665 666 void 667 cpu_boot_secondary_processors(void) 668 { 669 struct cpu_info *ci; 670 int i; 671 672 for (i = 0; i < PPC_MAXPROCS; i++) { 673 ci = &cpu_info[i]; 674 if (ci->ci_cpuid == 0) 675 continue; 676 ci->ci_randseed = (arc4random() & 0x7fffffff) + 1; 677 678 clockqueue_init(&ci->ci_queue); 679 sched_init_cpu(ci); 680 681 cpu_spinup(NULL, ci); 682 } 683 684 start_secondary_cpu = 1; 685 __asm volatile ("sync"); 686 } 687 688 void cpu_startclock(void); 689 690 void 691 cpu_hatch(void) 692 { 693 volatile struct cpu_hatch_data *h = cpu_hatch_data; 694 int intrstate; 695 696 /* Initialize timebase. */ 697 ppc_mttb(0); 698 699 /* Initialize curcpu(). */ 700 ppc_mtsprg0((u_int)h->ci); 701 702 ppc_mtibat0u(0); 703 ppc_mtibat1u(0); 704 ppc_mtibat2u(0); 705 ppc_mtibat3u(0); 706 ppc_mtdbat0u(0); 707 ppc_mtdbat1u(0); 708 ppc_mtdbat2u(0); 709 ppc_mtdbat3u(0); 710 711 if (ppc_proc_is_64b) { 712 /* 713 * The Hardware Interrupt Offset Register should be 714 * cleared after initialization. 715 */ 716 ppc_mthior(0); 717 __asm volatile ("sync"); 718 719 ppc_mthid0(h->hid0); 720 ppc64_mthid1(h->hid1); 721 ppc64_mthid4(h->hid4); 722 ppc64_mthid5(h->hid5); 723 } else if (h->l2cr != 0) { 724 u_int x; 725 726 ppc_mthid0(h->hid0); 727 ppc_mtl2cr(h->l2cr & ~L2CR_L2E); 728 729 /* Wait for L2 clock to be stable (640 L2 clocks). */ 730 delay(100); 731 732 /* Invalidate all L2 contents. */ 733 ppc_mtl2cr((h->l2cr & ~L2CR_L2E)|L2CR_L2I); 734 do { 735 x = ppc_mfl2cr(); 736 } while (x & L2CR_L2IP); 737 738 ppc_mtl2cr(h->l2cr); 739 } 740 741 /* 742 * Now enable translation (and machine checks/recoverable interrupts). 743 */ 744 pmap_enable_mmu(); 745 746 /* XXX OpenPIC */ 747 { 748 /* Sync timebase. */ 749 while (h->running == -1) 750 ; 751 __asm volatile ("sync; isync"); 752 ppc_mttb(h->tb); 753 } 754 755 ncpus++; 756 h->running = 1; 757 __asm volatile ("eieio" ::: "memory"); 758 759 while (start_secondary_cpu == 0) 760 ; 761 762 __asm volatile ("sync; isync"); 763 764 curcpu()->ci_ipending = 0; 765 curcpu()->ci_cpl = 0; 766 767 intrstate = ppc_intr_disable(); 768 cpu_startclock(); 769 ppc_intr_enable(intrstate); 770 771 /* Enable inter-processor interrupts. */ 772 openpic_set_priority(curcpu()->ci_cpuid, 14); 773 774 sched_toidle(); 775 } 776 #endif 777