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