1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2008-2012 Semihalf. 5 * All rights reserved. 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 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "opt_platform.h" 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/kernel.h> 36 #include <sys/module.h> 37 #include <sys/bus.h> 38 #include <sys/pcpu.h> 39 #include <sys/proc.h> 40 #include <sys/smp.h> 41 42 #include <machine/bus.h> 43 #include <machine/cpu.h> 44 #include <machine/hid.h> 45 #include <machine/_inttypes.h> 46 #include <machine/machdep.h> 47 #include <machine/md_var.h> 48 #include <machine/platform.h> 49 #include <machine/platformvar.h> 50 #include <machine/smp.h> 51 #include <machine/spr.h> 52 #include <machine/vmparam.h> 53 54 #include <dev/fdt/fdt_common.h> 55 #include <dev/ofw/ofw_bus.h> 56 #include <dev/ofw/ofw_bus_subr.h> 57 #include <dev/ofw/openfirm.h> 58 59 #include <vm/vm.h> 60 #include <vm/pmap.h> 61 #include <vm/vm_extern.h> 62 63 #include <powerpc/mpc85xx/mpc85xx.h> 64 65 #include "platform_if.h" 66 67 #ifdef SMP 68 extern void *ap_pcpu; 69 extern vm_paddr_t kernload; /* Kernel physical load address */ 70 extern uint8_t __boot_page[]; /* Boot page body */ 71 extern vm_paddr_t bp_kernload; /* Boot page copy of kernload */ 72 extern vm_offset_t bp_virtaddr; /* Virtual address of boot page */ 73 extern vm_offset_t __startkernel; 74 75 struct cpu_release { 76 uint32_t entry_h; 77 uint32_t entry_l; 78 uint32_t r3_h; 79 uint32_t r3_l; 80 uint32_t reserved; 81 uint32_t pir; 82 }; 83 #endif 84 85 extern uint32_t *bootinfo; 86 vm_paddr_t ccsrbar_pa; 87 vm_offset_t ccsrbar_va; 88 vm_size_t ccsrbar_size; 89 90 static int cpu, maxcpu; 91 92 static device_t rcpm_dev; 93 static void dummy_freeze(device_t, bool); 94 95 static void (*freeze_timebase)(device_t, bool) = dummy_freeze; 96 97 static int mpc85xx_probe(platform_t); 98 static void mpc85xx_mem_regions(platform_t, struct mem_region *phys, 99 int *physsz, struct mem_region *avail, int *availsz); 100 static u_long mpc85xx_timebase_freq(platform_t, struct cpuref *cpuref); 101 static int mpc85xx_smp_first_cpu(platform_t, struct cpuref *cpuref); 102 static int mpc85xx_smp_next_cpu(platform_t, struct cpuref *cpuref); 103 static int mpc85xx_smp_get_bsp(platform_t, struct cpuref *cpuref); 104 static int mpc85xx_smp_start_cpu(platform_t, struct pcpu *cpu); 105 static void mpc85xx_smp_timebase_sync(platform_t, u_long tb, int ap); 106 107 static void mpc85xx_reset(platform_t); 108 109 static platform_method_t mpc85xx_methods[] = { 110 PLATFORMMETHOD(platform_probe, mpc85xx_probe), 111 PLATFORMMETHOD(platform_attach, mpc85xx_attach), 112 PLATFORMMETHOD(platform_mem_regions, mpc85xx_mem_regions), 113 PLATFORMMETHOD(platform_timebase_freq, mpc85xx_timebase_freq), 114 115 PLATFORMMETHOD(platform_smp_first_cpu, mpc85xx_smp_first_cpu), 116 PLATFORMMETHOD(platform_smp_next_cpu, mpc85xx_smp_next_cpu), 117 PLATFORMMETHOD(platform_smp_get_bsp, mpc85xx_smp_get_bsp), 118 PLATFORMMETHOD(platform_smp_start_cpu, mpc85xx_smp_start_cpu), 119 PLATFORMMETHOD(platform_smp_timebase_sync, mpc85xx_smp_timebase_sync), 120 121 PLATFORMMETHOD(platform_reset, mpc85xx_reset), 122 123 PLATFORMMETHOD_END 124 }; 125 126 DEFINE_CLASS_0(mpc85xx, mpc85xx_platform, mpc85xx_methods, 0); 127 128 PLATFORM_DEF(mpc85xx_platform); 129 130 static int 131 mpc85xx_probe(platform_t plat) 132 { 133 u_int pvr = (mfpvr() >> 16) & 0xFFFF; 134 135 switch (pvr) { 136 case FSL_E500v1: 137 case FSL_E500v2: 138 case FSL_E500mc: 139 case FSL_E5500: 140 case FSL_E6500: 141 return (BUS_PROBE_DEFAULT); 142 } 143 return (ENXIO); 144 } 145 146 int 147 mpc85xx_attach(platform_t plat) 148 { 149 phandle_t cpus, child, ccsr; 150 const char *soc_name_guesses[] = {"/soc", "soc", NULL}; 151 const char **name; 152 pcell_t ranges[6], acells, pacells, scells; 153 uint64_t ccsrbar, ccsrsize; 154 int i; 155 156 if ((cpus = OF_finddevice("/cpus")) != -1) { 157 for (maxcpu = 0, child = OF_child(cpus); child != 0; 158 child = OF_peer(child), maxcpu++) 159 ; 160 } else 161 maxcpu = 1; 162 163 /* 164 * Locate CCSR region. Irritatingly, there is no way to find it 165 * unless you already know where it is. Try to infer its location 166 * from the device tree. 167 */ 168 169 ccsr = -1; 170 for (name = soc_name_guesses; *name != NULL && ccsr == -1; name++) 171 ccsr = OF_finddevice(*name); 172 if (ccsr == -1) { 173 char type[64]; 174 175 /* That didn't work. Search for devices of type "soc" */ 176 child = OF_child(OF_peer(0)); 177 for (OF_child(child); child != 0; child = OF_peer(child)) { 178 if (OF_getprop(child, "device_type", type, sizeof(type)) 179 <= 0) 180 continue; 181 182 if (strcmp(type, "soc") == 0) { 183 ccsr = child; 184 break; 185 } 186 } 187 } 188 189 if (ccsr == -1) 190 panic("Could not locate CCSR window!"); 191 192 OF_getprop(ccsr, "#size-cells", &scells, sizeof(scells)); 193 OF_getprop(ccsr, "#address-cells", &acells, sizeof(acells)); 194 OF_searchprop(OF_parent(ccsr), "#address-cells", &pacells, 195 sizeof(pacells)); 196 OF_getprop(ccsr, "ranges", ranges, sizeof(ranges)); 197 ccsrbar = ccsrsize = 0; 198 for (i = acells; i < acells + pacells; i++) { 199 ccsrbar <<= 32; 200 ccsrbar |= ranges[i]; 201 } 202 for (i = acells + pacells; i < acells + pacells + scells; i++) { 203 ccsrsize <<= 32; 204 ccsrsize |= ranges[i]; 205 } 206 ccsrbar_va = pmap_early_io_map(ccsrbar, ccsrsize); 207 ccsrbar_pa = ccsrbar; 208 ccsrbar_size = ccsrsize; 209 210 mpc85xx_enable_l3_cache(); 211 212 return (0); 213 } 214 215 void 216 mpc85xx_mem_regions(platform_t plat, struct mem_region *phys, int *physsz, 217 struct mem_region *avail, int *availsz) 218 { 219 220 ofw_mem_regions(phys, physsz, avail, availsz); 221 } 222 223 static u_long 224 mpc85xx_timebase_freq(platform_t plat, struct cpuref *cpuref) 225 { 226 u_long ticks; 227 phandle_t cpus, child; 228 pcell_t freq; 229 230 if (bootinfo != NULL) { 231 if (bootinfo[0] == 1) { 232 /* Backward compatibility. See 8-STABLE. */ 233 ticks = bootinfo[3] >> 3; 234 } else { 235 /* Compatibility with Juniper's loader. */ 236 ticks = bootinfo[5] >> 3; 237 } 238 } else 239 ticks = 0; 240 241 if ((cpus = OF_finddevice("/cpus")) == -1) 242 goto out; 243 244 if ((child = OF_child(cpus)) == 0) 245 goto out; 246 247 switch (OF_getproplen(child, "timebase-frequency")) { 248 case 4: 249 { 250 uint32_t tbase; 251 OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase)); 252 ticks = tbase; 253 return (ticks); 254 } 255 case 8: 256 { 257 uint64_t tbase; 258 OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase)); 259 ticks = tbase; 260 return (ticks); 261 } 262 default: 263 break; 264 } 265 266 freq = 0; 267 if (OF_getprop(child, "bus-frequency", (void *)&freq, 268 sizeof(freq)) <= 0) 269 goto out; 270 271 if (freq == 0) 272 goto out; 273 274 /* 275 * Time Base and Decrementer are updated every 8 CCB bus clocks. 276 * HID0[SEL_TBCLK] = 0 277 */ 278 if (mpc85xx_is_qoriq()) 279 ticks = freq / 32; 280 else 281 ticks = freq / 8; 282 283 out: 284 if (ticks <= 0) 285 panic("Unable to determine timebase frequency!"); 286 287 return (ticks); 288 } 289 290 static int 291 mpc85xx_smp_first_cpu(platform_t plat, struct cpuref *cpuref) 292 { 293 294 cpu = 0; 295 cpuref->cr_cpuid = cpu; 296 cpuref->cr_hwref = cpuref->cr_cpuid; 297 if (bootverbose) 298 printf("powerpc_smp_first_cpu: cpuid %d\n", cpuref->cr_cpuid); 299 cpu++; 300 301 return (0); 302 } 303 304 static int 305 mpc85xx_smp_next_cpu(platform_t plat, struct cpuref *cpuref) 306 { 307 308 if (cpu >= maxcpu) 309 return (ENOENT); 310 311 cpuref->cr_cpuid = cpu++; 312 cpuref->cr_hwref = cpuref->cr_cpuid; 313 if (bootverbose) 314 printf("powerpc_smp_next_cpu: cpuid %d\n", cpuref->cr_cpuid); 315 316 return (0); 317 } 318 319 static int 320 mpc85xx_smp_get_bsp(platform_t plat, struct cpuref *cpuref) 321 { 322 323 cpuref->cr_cpuid = mfspr(SPR_PIR); 324 cpuref->cr_hwref = cpuref->cr_cpuid; 325 326 return (0); 327 } 328 329 #ifdef SMP 330 static int 331 mpc85xx_smp_start_cpu_epapr(platform_t plat, struct pcpu *pc) 332 { 333 vm_paddr_t rel_pa, bptr; 334 volatile struct cpu_release *rel; 335 vm_offset_t rel_va, rel_page; 336 phandle_t node; 337 int i; 338 339 /* If we're calling this, the node already exists. */ 340 node = OF_finddevice("/cpus"); 341 for (i = 0, node = OF_child(node); i < pc->pc_cpuid; 342 i++, node = OF_peer(node)) 343 ; 344 if (OF_getencprop(node, "cpu-release-addr", (pcell_t *)&rel_pa, 345 sizeof(rel_pa)) == -1) { 346 return (ENOENT); 347 } 348 349 rel_page = kva_alloc(PAGE_SIZE); 350 if (rel_page == 0) 351 return (ENOMEM); 352 353 critical_enter(); 354 rel_va = rel_page + (rel_pa & PAGE_MASK); 355 pmap_kenter(rel_page, rel_pa & ~PAGE_MASK); 356 rel = (struct cpu_release *)rel_va; 357 bptr = pmap_kextract((uintptr_t)__boot_page); 358 359 cpu_flush_dcache(__DEVOLATILE(struct cpu_release *,rel), sizeof(*rel)); 360 rel->pir = pc->pc_cpuid; __asm __volatile("sync" ::: "memory"); 361 rel->entry_h = (bptr >> 32); __asm __volatile("sync" ::: "memory"); 362 cpu_flush_dcache(__DEVOLATILE(struct cpu_release *,rel), sizeof(*rel)); 363 rel->entry_l = bptr & 0xffffffff; __asm __volatile("sync" ::: "memory"); 364 cpu_flush_dcache(__DEVOLATILE(struct cpu_release *,rel), sizeof(*rel)); 365 if (bootverbose) 366 printf("Waking up CPU %d via CPU release page %p\n", 367 pc->pc_cpuid, rel); 368 critical_exit(); 369 pmap_kremove(rel_page); 370 kva_free(rel_page, PAGE_SIZE); 371 372 return (0); 373 } 374 #endif 375 376 static int 377 mpc85xx_smp_start_cpu(platform_t plat, struct pcpu *pc) 378 { 379 #ifdef SMP 380 vm_paddr_t bptr; 381 uint32_t reg; 382 int timeout; 383 uintptr_t brr; 384 int cpuid; 385 int epapr_boot = 0; 386 uint32_t tgt; 387 388 if (mpc85xx_is_qoriq()) { 389 reg = ccsr_read4(OCP85XX_COREDISR); 390 cpuid = pc->pc_cpuid; 391 392 if ((reg & (1 << cpuid)) != 0) { 393 printf("%s: CPU %d is disabled!\n", __func__, pc->pc_cpuid); 394 return (-1); 395 } 396 397 brr = OCP85XX_BRR; 398 } else { 399 brr = OCP85XX_EEBPCR; 400 cpuid = pc->pc_cpuid + 24; 401 } 402 bp_kernload = kernload; 403 bp_virtaddr = (vm_offset_t)&__boot_page; 404 /* 405 * bp_kernload and bp_virtaddr are in the boot page. Sync the cache 406 * because ePAPR booting has the other core(s) already running. 407 */ 408 cpu_flush_dcache(&bp_kernload, sizeof(bp_kernload)); 409 cpu_flush_dcache(&bp_virtaddr, sizeof(bp_virtaddr)); 410 411 ap_pcpu = pc; 412 __asm __volatile("msync; isync"); 413 414 /* First try the ePAPR way. */ 415 if (mpc85xx_smp_start_cpu_epapr(plat, pc) == 0) { 416 epapr_boot = 1; 417 goto spin_wait; 418 } 419 420 reg = ccsr_read4(brr); 421 if ((reg & (1 << cpuid)) != 0) { 422 printf("SMP: CPU %d already out of hold-off state!\n", 423 pc->pc_cpuid); 424 return (ENXIO); 425 } 426 427 /* Flush caches to have our changes hit DRAM. */ 428 cpu_flush_dcache(__boot_page, 4096); 429 430 bptr = pmap_kextract((uintptr_t)__boot_page); 431 KASSERT((bptr & 0xfff) == 0, 432 ("%s: boot page is not aligned (%#jx)", __func__, (uintmax_t)bptr)); 433 if (mpc85xx_is_qoriq()) { 434 /* 435 * Read DDR controller configuration to select proper BPTR target ID. 436 * 437 * On P5020 bit 29 of DDR1_CS0_CONFIG enables DDR controllers 438 * interleaving. If this bit is set, we have to use 439 * OCP85XX_TGTIF_RAM_INTL as BPTR target ID. On other QorIQ DPAA SoCs, 440 * this bit is reserved and always 0. 441 */ 442 443 reg = ccsr_read4(OCP85XX_DDR1_CS0_CONFIG); 444 if (reg & (1 << 29)) 445 tgt = OCP85XX_TGTIF_RAM_INTL; 446 else 447 tgt = OCP85XX_TGTIF_RAM1; 448 449 /* 450 * Set BSTR to the physical address of the boot page 451 */ 452 ccsr_write4(OCP85XX_BSTRH, bptr >> 32); 453 ccsr_write4(OCP85XX_BSTRL, bptr); 454 ccsr_write4(OCP85XX_BSTAR, OCP85XX_ENA_MASK | 455 (tgt << OCP85XX_TRGT_SHIFT_QORIQ) | (ffsl(PAGE_SIZE) - 2)); 456 457 /* Read back OCP85XX_BSTAR to synchronize write */ 458 ccsr_read4(OCP85XX_BSTAR); 459 460 /* 461 * Enable and configure time base on new CPU. 462 */ 463 464 /* Set TB clock source to platform clock / 32 */ 465 reg = ccsr_read4(CCSR_CTBCKSELR); 466 ccsr_write4(CCSR_CTBCKSELR, reg & ~(1 << pc->pc_cpuid)); 467 468 /* Enable TB */ 469 reg = ccsr_read4(CCSR_CTBENR); 470 ccsr_write4(CCSR_CTBENR, reg | (1 << pc->pc_cpuid)); 471 } else { 472 /* 473 * Set BPTR to the physical address of the boot page 474 */ 475 bptr = (bptr >> 12) | 0x80000000u; 476 ccsr_write4(OCP85XX_BPTR, bptr); 477 __asm __volatile("isync; msync"); 478 } 479 480 /* 481 * Release AP from hold-off state 482 */ 483 reg = ccsr_read4(brr); 484 ccsr_write4(brr, reg | (1 << cpuid)); 485 __asm __volatile("isync; msync"); 486 487 spin_wait: 488 timeout = 500; 489 while (!pc->pc_awake && timeout--) 490 DELAY(1000); /* wait 1ms */ 491 492 /* 493 * Disable boot page translation so that the 4K page at the default 494 * address (= 0xfffff000) isn't permanently remapped and thus not 495 * usable otherwise. 496 */ 497 if (!epapr_boot) { 498 if (mpc85xx_is_qoriq()) 499 ccsr_write4(OCP85XX_BSTAR, 0); 500 else 501 ccsr_write4(OCP85XX_BPTR, 0); 502 __asm __volatile("isync; msync"); 503 } 504 505 if (!pc->pc_awake) 506 panic("SMP: CPU %d didn't wake up.\n", pc->pc_cpuid); 507 return ((pc->pc_awake) ? 0 : EBUSY); 508 #else 509 /* No SMP support */ 510 return (ENXIO); 511 #endif 512 } 513 514 static void 515 mpc85xx_reset(platform_t plat) 516 { 517 518 /* 519 * Try the dedicated reset register first. 520 * If the SoC doesn't have one, we'll fall 521 * back to using the debug control register. 522 */ 523 ccsr_write4(OCP85XX_RSTCR, 2); 524 525 mtmsr(mfmsr() & ~PSL_DE); 526 527 /* Enable debug interrupts and issue reset. */ 528 mtspr(SPR_DBCR0, DBCR0_IDM | DBCR0_RST_SYSTEM); 529 __asm __volatile("isync"); 530 531 /* Enable Debug Interrupts in MSR. */ 532 mtmsr(mfmsr() | PSL_DE); 533 534 printf("Reset failed...\n"); 535 while (1) 536 ; 537 } 538 539 static void 540 mpc85xx_smp_timebase_sync(platform_t plat, u_long tb, int ap) 541 { 542 static volatile bool tb_ready; 543 static volatile int cpu_done; 544 545 if (ap) { 546 /* APs. Hold off until we get a stable timebase. */ 547 while (!tb_ready) 548 atomic_thread_fence_seq_cst(); 549 mttb(tb); 550 atomic_add_int(&cpu_done, 1); 551 while (cpu_done < mp_ncpus) 552 atomic_thread_fence_seq_cst(); 553 } else { 554 /* BSP */ 555 freeze_timebase(rcpm_dev, true); 556 tb_ready = true; 557 mttb(tb); 558 atomic_add_int(&cpu_done, 1); 559 while (cpu_done < mp_ncpus) 560 atomic_thread_fence_seq_cst(); 561 freeze_timebase(rcpm_dev, false); 562 } 563 } 564 565 /* Fallback freeze. In case no real handler is found in the device tree. */ 566 static void 567 dummy_freeze(device_t dev, bool freeze) 568 { 569 /* Nothing to do here, move along. */ 570 } 571 572 /* QorIQ Run control/power management timebase management. */ 573 574 #define RCPM_CTBENR 0x00000084 575 struct mpc85xx_rcpm_softc { 576 struct resource *sc_mem; 577 }; 578 579 static void 580 mpc85xx_rcpm_freeze_timebase(device_t dev, bool freeze) 581 { 582 struct mpc85xx_rcpm_softc *sc; 583 584 sc = device_get_softc(dev); 585 586 if (freeze) 587 bus_write_4(sc->sc_mem, RCPM_CTBENR, 0); 588 else 589 bus_write_4(sc->sc_mem, RCPM_CTBENR, (1 << maxcpu) - 1); 590 } 591 592 static int 593 mpc85xx_rcpm_probe(device_t dev) 594 { 595 if (!ofw_bus_is_compatible(dev, "fsl,qoriq-rcpm-1.0")) 596 return (ENXIO); 597 598 device_set_desc(dev, "QorIQ Run control and power management"); 599 return (BUS_PROBE_GENERIC); 600 } 601 602 static int 603 mpc85xx_rcpm_attach(device_t dev) 604 { 605 struct mpc85xx_rcpm_softc *sc; 606 int rid; 607 608 sc = device_get_softc(dev); 609 freeze_timebase = mpc85xx_rcpm_freeze_timebase; 610 rcpm_dev = dev; 611 612 rid = 0; 613 sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 614 RF_ACTIVE | RF_SHAREABLE); 615 616 return (0); 617 } 618 619 static device_method_t mpc85xx_rcpm_methods[] = { 620 DEVMETHOD(device_probe, mpc85xx_rcpm_probe), 621 DEVMETHOD(device_attach, mpc85xx_rcpm_attach), 622 DEVMETHOD_END 623 }; 624 625 static driver_t mpc85xx_rcpm_driver = { 626 "rcpm", 627 mpc85xx_rcpm_methods, 628 sizeof(struct mpc85xx_rcpm_softc) 629 }; 630 631 EARLY_DRIVER_MODULE(mpc85xx_rcpm, simplebus, mpc85xx_rcpm_driver, 0, 0, 632 BUS_PASS_BUS); 633 634 /* "Global utilities" power management/Timebase management. */ 635 636 #define GUTS_DEVDISR 0x00000070 637 #define DEVDISR_TB0 0x00004000 638 #define DEVDISR_TB1 0x00001000 639 640 struct mpc85xx_guts_softc { 641 struct resource *sc_mem; 642 }; 643 644 static void 645 mpc85xx_guts_freeze_timebase(device_t dev, bool freeze) 646 { 647 struct mpc85xx_guts_softc *sc; 648 uint32_t devdisr; 649 650 sc = device_get_softc(dev); 651 652 devdisr = bus_read_4(sc->sc_mem, GUTS_DEVDISR); 653 if (freeze) 654 bus_write_4(sc->sc_mem, GUTS_DEVDISR, 655 devdisr | (DEVDISR_TB0 | DEVDISR_TB1)); 656 else 657 bus_write_4(sc->sc_mem, GUTS_DEVDISR, 658 devdisr & ~(DEVDISR_TB0 | DEVDISR_TB1)); 659 } 660 661 static int 662 mpc85xx_guts_probe(device_t dev) 663 { 664 if (!ofw_bus_is_compatible(dev, "fsl,mpc8572-guts") && 665 !ofw_bus_is_compatible(dev, "fsl,p1020-guts") && 666 !ofw_bus_is_compatible(dev, "fsl,p1021-guts") && 667 !ofw_bus_is_compatible(dev, "fsl,p1022-guts") && 668 !ofw_bus_is_compatible(dev, "fsl,p1023-guts") && 669 !ofw_bus_is_compatible(dev, "fsl,p2020-guts")) 670 return (ENXIO); 671 672 device_set_desc(dev, "MPC85xx Global Utilities"); 673 return (BUS_PROBE_GENERIC); 674 } 675 676 static int 677 mpc85xx_guts_attach(device_t dev) 678 { 679 struct mpc85xx_rcpm_softc *sc; 680 int rid; 681 682 sc = device_get_softc(dev); 683 freeze_timebase = mpc85xx_guts_freeze_timebase; 684 rcpm_dev = dev; 685 686 rid = 0; 687 sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 688 RF_ACTIVE | RF_SHAREABLE); 689 690 return (0); 691 } 692 693 static device_method_t mpc85xx_guts_methods[] = { 694 DEVMETHOD(device_probe, mpc85xx_guts_probe), 695 DEVMETHOD(device_attach, mpc85xx_guts_attach), 696 DEVMETHOD_END 697 }; 698 699 static driver_t mpc85xx_guts_driver = { 700 "guts", 701 mpc85xx_guts_methods, 702 sizeof(struct mpc85xx_guts_softc) 703 }; 704 705 EARLY_DRIVER_MODULE(mpc85xx_guts, simplebus, mpc85xx_guts_driver, 0, 0, 706 BUS_PASS_BUS); 707