1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (C) 2002 Benno Rice. 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 * 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 * 16 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 * $FreeBSD$ 28 */ 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/module.h> 33 #include <sys/bus.h> 34 #include <sys/conf.h> 35 #include <sys/kernel.h> 36 37 #include <dev/ofw/openfirm.h> 38 #include <dev/ofw/ofw_pci.h> 39 #include <dev/ofw/ofw_bus.h> 40 #include <dev/ofw/ofw_bus_subr.h> 41 42 #include <dev/pci/pcivar.h> 43 #include <dev/pci/pcireg.h> 44 45 #include <machine/bus.h> 46 #include <machine/intr_machdep.h> 47 #include <machine/md_var.h> 48 #include <machine/pio.h> 49 #include <machine/resource.h> 50 51 #include <sys/rman.h> 52 53 #include <powerpc/powermac/uninorthvar.h> 54 55 #include <vm/vm.h> 56 #include <vm/pmap.h> 57 58 /* 59 * Driver for the Uninorth chip itself. 60 */ 61 62 static MALLOC_DEFINE(M_UNIN, "unin", "unin device information"); 63 64 /* 65 * Device interface. 66 */ 67 68 static int unin_chip_probe(device_t); 69 static int unin_chip_attach(device_t); 70 71 /* 72 * Bus interface. 73 */ 74 static int unin_chip_print_child(device_t dev, device_t child); 75 static void unin_chip_probe_nomatch(device_t, device_t); 76 static struct resource *unin_chip_alloc_resource(device_t, device_t, int, int *, 77 rman_res_t, rman_res_t, 78 rman_res_t, u_int); 79 static int unin_chip_activate_resource(device_t, device_t, int, int, 80 struct resource *); 81 static int unin_chip_deactivate_resource(device_t, device_t, int, int, 82 struct resource *); 83 static int unin_chip_release_resource(device_t, device_t, int, int, 84 struct resource *); 85 static struct resource_list *unin_chip_get_resource_list (device_t, device_t); 86 87 /* 88 * OFW Bus interface 89 */ 90 91 static ofw_bus_get_devinfo_t unin_chip_get_devinfo; 92 93 /* 94 * Local routines 95 */ 96 97 static void unin_enable_gmac(device_t dev); 98 static void unin_enable_mpic(device_t dev); 99 100 /* 101 * Driver methods. 102 */ 103 static device_method_t unin_chip_methods[] = { 104 105 /* Device interface */ 106 DEVMETHOD(device_probe, unin_chip_probe), 107 DEVMETHOD(device_attach, unin_chip_attach), 108 109 /* Bus interface */ 110 DEVMETHOD(bus_print_child, unin_chip_print_child), 111 DEVMETHOD(bus_probe_nomatch, unin_chip_probe_nomatch), 112 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 113 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 114 115 DEVMETHOD(bus_alloc_resource, unin_chip_alloc_resource), 116 DEVMETHOD(bus_release_resource, unin_chip_release_resource), 117 DEVMETHOD(bus_activate_resource, unin_chip_activate_resource), 118 DEVMETHOD(bus_deactivate_resource, unin_chip_deactivate_resource), 119 DEVMETHOD(bus_get_resource_list, unin_chip_get_resource_list), 120 121 DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), 122 123 /* ofw_bus interface */ 124 DEVMETHOD(ofw_bus_get_devinfo, unin_chip_get_devinfo), 125 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 126 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 127 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 128 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 129 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 130 131 { 0, 0 } 132 }; 133 134 static driver_t unin_chip_driver = { 135 "unin", 136 unin_chip_methods, 137 sizeof(struct unin_chip_softc) 138 }; 139 140 static devclass_t unin_chip_devclass; 141 142 /* 143 * Assume there is only one unin chip in a PowerMac, so that pmu.c functions can 144 * suspend the chip after the whole rest of the device tree is suspended, not 145 * earlier. 146 */ 147 static device_t unin_chip; 148 149 EARLY_DRIVER_MODULE(unin, ofwbus, unin_chip_driver, unin_chip_devclass, 0, 0, 150 BUS_PASS_BUS); 151 152 /* 153 * Add an interrupt to the dev's resource list if present 154 */ 155 static void 156 unin_chip_add_intr(phandle_t devnode, struct unin_chip_devinfo *dinfo) 157 { 158 phandle_t iparent; 159 int *intr; 160 int i, nintr; 161 int icells; 162 163 if (dinfo->udi_ninterrupts >= 6) { 164 printf("unin: device has more than 6 interrupts\n"); 165 return; 166 } 167 168 nintr = OF_getprop_alloc_multi(devnode, "interrupts", sizeof(*intr), 169 (void **)&intr); 170 if (nintr == -1) { 171 nintr = OF_getprop_alloc_multi(devnode, "AAPL,interrupts", 172 sizeof(*intr), (void **)&intr); 173 if (nintr == -1) 174 return; 175 } 176 177 if (intr[0] == -1) 178 return; 179 180 if (OF_getprop(devnode, "interrupt-parent", &iparent, sizeof(iparent)) 181 <= 0) 182 panic("Interrupt but no interrupt parent!\n"); 183 184 if (OF_searchprop(iparent, "#interrupt-cells", &icells, sizeof(icells)) 185 <= 0) 186 icells = 1; 187 188 for (i = 0; i < nintr; i+=icells) { 189 u_int irq = MAP_IRQ(iparent, intr[i]); 190 191 resource_list_add(&dinfo->udi_resources, SYS_RES_IRQ, 192 dinfo->udi_ninterrupts, irq, irq, 1); 193 194 if (icells > 1) { 195 powerpc_config_intr(irq, 196 (intr[i+1] & 1) ? INTR_TRIGGER_LEVEL : 197 INTR_TRIGGER_EDGE, INTR_POLARITY_LOW); 198 } 199 200 dinfo->udi_interrupts[dinfo->udi_ninterrupts] = irq; 201 dinfo->udi_ninterrupts++; 202 } 203 } 204 205 static void 206 unin_chip_add_reg(phandle_t devnode, struct unin_chip_devinfo *dinfo) 207 { 208 struct unin_chip_reg *reg; 209 int i, nreg; 210 211 nreg = OF_getprop_alloc_multi(devnode, "reg", sizeof(*reg), (void **)®); 212 if (nreg == -1) 213 return; 214 215 for (i = 0; i < nreg; i++) { 216 resource_list_add(&dinfo->udi_resources, SYS_RES_MEMORY, i, 217 reg[i].mr_base, 218 reg[i].mr_base + reg[i].mr_size, 219 reg[i].mr_size); 220 } 221 } 222 223 static void 224 unin_update_reg(device_t dev, uint32_t regoff, uint32_t set, uint32_t clr) 225 { 226 volatile u_int *reg; 227 struct unin_chip_softc *sc; 228 u_int32_t tmpl; 229 230 sc = device_get_softc(dev); 231 reg = (void *)(sc->sc_addr + regoff); 232 tmpl = inl(reg); 233 tmpl &= ~clr; 234 tmpl |= set; 235 outl(reg, tmpl); 236 } 237 238 static void 239 unin_enable_gmac(device_t dev) 240 { 241 unin_update_reg(dev, UNIN_CLOCKCNTL, UNIN_CLOCKCNTL_GMAC, 0); 242 } 243 244 static void 245 unin_enable_mpic(device_t dev) 246 { 247 unin_update_reg(dev, UNIN_TOGGLE_REG, UNIN_MPIC_RESET | UNIN_MPIC_OUTPUT_ENABLE, 0); 248 } 249 250 static int 251 unin_chip_probe(device_t dev) 252 { 253 const char *name; 254 255 name = ofw_bus_get_name(dev); 256 257 if (name == NULL) 258 return (ENXIO); 259 260 if (strcmp(name, "uni-n") != 0 && strcmp(name, "u3") != 0 261 && strcmp(name, "u4") != 0) 262 return (ENXIO); 263 264 device_set_desc(dev, "Apple UniNorth System Controller"); 265 return (0); 266 } 267 268 static int 269 unin_chip_attach(device_t dev) 270 { 271 struct unin_chip_softc *sc; 272 struct unin_chip_devinfo *dinfo; 273 phandle_t root; 274 phandle_t child; 275 phandle_t iparent; 276 device_t cdev; 277 cell_t acells, scells; 278 char compat[32]; 279 char name[32]; 280 u_int irq, reg[3]; 281 int error, i = 0; 282 283 sc = device_get_softc(dev); 284 root = ofw_bus_get_node(dev); 285 286 if (OF_getprop(root, "reg", reg, sizeof(reg)) < 8) 287 return (ENXIO); 288 289 acells = scells = 1; 290 OF_getprop(OF_parent(root), "#address-cells", &acells, sizeof(acells)); 291 OF_getprop(OF_parent(root), "#size-cells", &scells, sizeof(scells)); 292 293 i = 0; 294 sc->sc_physaddr = reg[i++]; 295 if (acells == 2) { 296 sc->sc_physaddr <<= 32; 297 sc->sc_physaddr |= reg[i++]; 298 } 299 sc->sc_size = reg[i++]; 300 if (scells == 2) { 301 sc->sc_size <<= 32; 302 sc->sc_size |= reg[i++]; 303 } 304 305 sc->sc_mem_rman.rm_type = RMAN_ARRAY; 306 sc->sc_mem_rman.rm_descr = "UniNorth Device Memory"; 307 308 error = rman_init(&sc->sc_mem_rman); 309 310 if (error) { 311 device_printf(dev, "rman_init() failed. error = %d\n", error); 312 return (error); 313 } 314 315 error = rman_manage_region(&sc->sc_mem_rman, sc->sc_physaddr, 316 sc->sc_physaddr + sc->sc_size - 1); 317 if (error) { 318 device_printf(dev, 319 "rman_manage_region() failed. error = %d\n", 320 error); 321 return (error); 322 } 323 324 if (unin_chip == NULL) 325 unin_chip = dev; 326 327 /* 328 * Iterate through the sub-devices 329 */ 330 for (child = OF_child(root); child != 0; child = OF_peer(child)) { 331 dinfo = malloc(sizeof(*dinfo), M_UNIN, M_WAITOK | M_ZERO); 332 if (ofw_bus_gen_setup_devinfo(&dinfo->udi_obdinfo, child) 333 != 0) 334 { 335 free(dinfo, M_UNIN); 336 continue; 337 } 338 339 resource_list_init(&dinfo->udi_resources); 340 dinfo->udi_ninterrupts = 0; 341 unin_chip_add_intr(child, dinfo); 342 343 /* 344 * Some Apple machines do have a bug in OF, they miss 345 * the interrupt entries on the U3 I2C node. That means they 346 * do not have an entry with number of interrupts nor the 347 * entry of the interrupt parent handle. 348 * We define an interrupt and hardwire it to the /u3/mpic 349 * handle. 350 */ 351 352 if (OF_getprop(child, "name", name, sizeof(name)) <= 0) 353 device_printf(dev, "device has no name!\n"); 354 if (dinfo->udi_ninterrupts == 0 && 355 (strcmp(name, "i2c-bus") == 0 || 356 strcmp(name, "i2c") == 0)) { 357 if (OF_getprop(child, "interrupt-parent", &iparent, 358 sizeof(iparent)) <= 0) { 359 iparent = OF_finddevice("/u3/mpic"); 360 device_printf(dev, "Set /u3/mpic as iparent!\n"); 361 } 362 /* Add an interrupt number 0 to the parent. */ 363 irq = MAP_IRQ(iparent, 0); 364 resource_list_add(&dinfo->udi_resources, SYS_RES_IRQ, 365 dinfo->udi_ninterrupts, irq, irq, 1); 366 dinfo->udi_interrupts[dinfo->udi_ninterrupts] = irq; 367 dinfo->udi_ninterrupts++; 368 } 369 370 unin_chip_add_reg(child, dinfo); 371 372 cdev = device_add_child(dev, NULL, -1); 373 if (cdev == NULL) { 374 device_printf(dev, "<%s>: device_add_child failed\n", 375 dinfo->udi_obdinfo.obd_name); 376 resource_list_free(&dinfo->udi_resources); 377 ofw_bus_gen_destroy_devinfo(&dinfo->udi_obdinfo); 378 free(dinfo, M_UNIN); 379 continue; 380 } 381 382 device_set_ivars(cdev, dinfo); 383 } 384 385 /* 386 * Only map the first page, since that is where the registers 387 * of interest lie. 388 */ 389 sc->sc_addr = (vm_offset_t)pmap_mapdev(sc->sc_physaddr, PAGE_SIZE); 390 391 sc->sc_version = *(u_int *)sc->sc_addr; 392 device_printf(dev, "Version %d\n", sc->sc_version); 393 394 /* 395 * Enable the GMAC Ethernet cell and the integrated OpenPIC 396 * if Open Firmware says they are used. 397 */ 398 for (child = OF_child(root); child; child = OF_peer(child)) { 399 memset(compat, 0, sizeof(compat)); 400 OF_getprop(child, "compatible", compat, sizeof(compat)); 401 if (strcmp(compat, "gmac") == 0) 402 unin_enable_gmac(dev); 403 if (strcmp(compat, "chrp,open-pic") == 0) 404 unin_enable_mpic(dev); 405 } 406 407 /* 408 * GMAC lives under the PCI bus, so just check if enet is gmac. 409 */ 410 child = OF_finddevice("enet"); 411 memset(compat, 0, sizeof(compat)); 412 OF_getprop(child, "compatible", compat, sizeof(compat)); 413 if (strcmp(compat, "gmac") == 0) 414 unin_enable_gmac(dev); 415 416 return (bus_generic_attach(dev)); 417 } 418 419 static int 420 unin_chip_print_child(device_t dev, device_t child) 421 { 422 struct unin_chip_devinfo *dinfo; 423 struct resource_list *rl; 424 int retval = 0; 425 426 dinfo = device_get_ivars(child); 427 rl = &dinfo->udi_resources; 428 429 retval += bus_print_child_header(dev, child); 430 431 retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx"); 432 retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd"); 433 434 retval += bus_print_child_footer(dev, child); 435 436 return (retval); 437 } 438 439 static void 440 unin_chip_probe_nomatch(device_t dev, device_t child) 441 { 442 struct unin_chip_devinfo *dinfo; 443 struct resource_list *rl; 444 const char *type; 445 446 if (bootverbose) { 447 dinfo = device_get_ivars(child); 448 rl = &dinfo->udi_resources; 449 450 if ((type = ofw_bus_get_type(child)) == NULL) 451 type = "(unknown)"; 452 device_printf(dev, "<%s, %s>", type, ofw_bus_get_name(child)); 453 resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx"); 454 resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd"); 455 printf(" (no driver attached)\n"); 456 } 457 } 458 459 460 static struct resource * 461 unin_chip_alloc_resource(device_t bus, device_t child, int type, int *rid, 462 rman_res_t start, rman_res_t end, rman_res_t count, 463 u_int flags) 464 { 465 struct unin_chip_softc *sc; 466 int needactivate; 467 struct resource *rv; 468 struct rman *rm; 469 u_long adjstart, adjend, adjcount; 470 struct unin_chip_devinfo *dinfo; 471 struct resource_list_entry *rle; 472 473 sc = device_get_softc(bus); 474 dinfo = device_get_ivars(child); 475 476 needactivate = flags & RF_ACTIVE; 477 flags &= ~RF_ACTIVE; 478 479 switch (type) { 480 case SYS_RES_MEMORY: 481 case SYS_RES_IOPORT: 482 rle = resource_list_find(&dinfo->udi_resources, SYS_RES_MEMORY, 483 *rid); 484 if (rle == NULL) { 485 device_printf(bus, "no rle for %s memory %d\n", 486 device_get_nameunit(child), *rid); 487 return (NULL); 488 } 489 490 rle->end = rle->end - 1; /* Hack? */ 491 492 if (start < rle->start) 493 adjstart = rle->start; 494 else if (start > rle->end) 495 adjstart = rle->end; 496 else 497 adjstart = start; 498 499 if (end < rle->start) 500 adjend = rle->start; 501 else if (end > rle->end) 502 adjend = rle->end; 503 else 504 adjend = end; 505 506 adjcount = adjend - adjstart; 507 508 rm = &sc->sc_mem_rman; 509 break; 510 511 case SYS_RES_IRQ: 512 /* Check for passthrough from subattachments. */ 513 if (device_get_parent(child) != bus) 514 return BUS_ALLOC_RESOURCE(device_get_parent(bus), child, 515 type, rid, start, end, count, 516 flags); 517 518 rle = resource_list_find(&dinfo->udi_resources, SYS_RES_IRQ, 519 *rid); 520 if (rle == NULL) { 521 if (dinfo->udi_ninterrupts >= 6) { 522 device_printf(bus, 523 "%s has more than 6 interrupts\n", 524 device_get_nameunit(child)); 525 return (NULL); 526 } 527 resource_list_add(&dinfo->udi_resources, SYS_RES_IRQ, 528 dinfo->udi_ninterrupts, start, start, 529 1); 530 531 dinfo->udi_interrupts[dinfo->udi_ninterrupts] = start; 532 dinfo->udi_ninterrupts++; 533 } 534 535 return (resource_list_alloc(&dinfo->udi_resources, bus, child, 536 type, rid, start, end, count, 537 flags)); 538 default: 539 device_printf(bus, "unknown resource request from %s\n", 540 device_get_nameunit(child)); 541 return (NULL); 542 } 543 544 rv = rman_reserve_resource(rm, adjstart, adjend, adjcount, flags, 545 child); 546 if (rv == NULL) { 547 device_printf(bus, 548 "failed to reserve resource %#lx - %#lx (%#lx)" 549 " for %s\n", adjstart, adjend, adjcount, 550 device_get_nameunit(child)); 551 return (NULL); 552 } 553 554 rman_set_rid(rv, *rid); 555 556 if (needactivate) { 557 if (bus_activate_resource(child, type, *rid, rv) != 0) { 558 device_printf(bus, 559 "failed to activate resource for %s\n", 560 device_get_nameunit(child)); 561 rman_release_resource(rv); 562 return (NULL); 563 } 564 } 565 566 return (rv); 567 } 568 569 static int 570 unin_chip_release_resource(device_t bus, device_t child, int type, int rid, 571 struct resource *res) 572 { 573 if (rman_get_flags(res) & RF_ACTIVE) { 574 int error = bus_deactivate_resource(child, type, rid, res); 575 if (error) 576 return error; 577 } 578 579 return (rman_release_resource(res)); 580 } 581 582 static int 583 unin_chip_activate_resource(device_t bus, device_t child, int type, int rid, 584 struct resource *res) 585 { 586 void *p; 587 588 if (type == SYS_RES_IRQ) 589 return (bus_activate_resource(bus, type, rid, res)); 590 591 if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { 592 vm_offset_t start; 593 594 start = (vm_offset_t) rman_get_start(res); 595 596 if (bootverbose) 597 printf("unin mapdev: start %zx, len %jd\n", start, 598 rman_get_size(res)); 599 600 p = pmap_mapdev(start, (vm_size_t) rman_get_size(res)); 601 if (p == NULL) 602 return (ENOMEM); 603 rman_set_virtual(res, p); 604 rman_set_bustag(res, &bs_be_tag); 605 rman_set_bushandle(res, (u_long)p); 606 } 607 608 return (rman_activate_resource(res)); 609 } 610 611 612 static int 613 unin_chip_deactivate_resource(device_t bus, device_t child, int type, int rid, 614 struct resource *res) 615 { 616 /* 617 * If this is a memory resource, unmap it. 618 */ 619 if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { 620 u_int32_t psize; 621 622 psize = rman_get_size(res); 623 pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize); 624 } 625 626 return (rman_deactivate_resource(res)); 627 } 628 629 630 static struct resource_list * 631 unin_chip_get_resource_list (device_t dev, device_t child) 632 { 633 struct unin_chip_devinfo *dinfo; 634 635 dinfo = device_get_ivars(child); 636 return (&dinfo->udi_resources); 637 } 638 639 static const struct ofw_bus_devinfo * 640 unin_chip_get_devinfo(device_t dev, device_t child) 641 { 642 struct unin_chip_devinfo *dinfo; 643 644 dinfo = device_get_ivars(child); 645 return (&dinfo->udi_obdinfo); 646 } 647 648 int 649 unin_chip_wake(device_t dev) 650 { 651 652 if (dev == NULL) 653 dev = unin_chip; 654 unin_update_reg(dev, UNIN_PWR_MGMT, UNIN_PWR_NORMAL, UNIN_PWR_MASK); 655 DELAY(10); 656 unin_update_reg(dev, UNIN_HWINIT_STATE, UNIN_RUNNING, 0); 657 DELAY(100); 658 659 return (0); 660 } 661 662 int 663 unin_chip_sleep(device_t dev, int idle) 664 { 665 if (dev == NULL) 666 dev = unin_chip; 667 668 unin_update_reg(dev, UNIN_HWINIT_STATE, UNIN_SLEEPING, 0); 669 DELAY(10); 670 if (idle) 671 unin_update_reg(dev, UNIN_PWR_MGMT, UNIN_PWR_IDLE2, UNIN_PWR_MASK); 672 else 673 unin_update_reg(dev, UNIN_PWR_MGMT, UNIN_PWR_SLEEP, UNIN_PWR_MASK); 674 DELAY(10); 675 676 return (0); 677 } 678