upa.c revision 295832
1/*- 2 * Copyright (c) 2006 Marius Strobl <marius@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: head/sys/sparc64/sparc64/upa.c 295832 2016-02-20 01:32:58Z jhibbits $"); 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/bus.h> 33#include <sys/kernel.h> 34#include <sys/module.h> 35#include <sys/resource.h> 36#include <sys/rman.h> 37 38#include <dev/ofw/ofw_bus.h> 39#include <dev/ofw/ofw_bus_subr.h> 40#include <dev/ofw/openfirm.h> 41 42#include <machine/bus.h> 43#include <machine/bus_common.h> 44#include <machine/intr_machdep.h> 45#include <machine/resource.h> 46 47#define UPA_NREG 3 48 49#define UPA_CFG 0 50#define UPA_IMR1 1 51#define UPA_IMR2 2 52 53/* UPA_CFG bank */ 54#define UPA_CFG_UPA0 0x00 /* UPA0 config register */ 55#define UPA_CFG_UPA1 0x08 /* UPA1 config register */ 56#define UPA_CFG_IF 0x10 /* interface config register */ 57#define UPA_CFG_IF_RST 0x00 58#define UPA_CFG_IF_POK_RST 0x02 59#define UPA_CFG_IF_POK 0x03 60#define UPA_CFG_ESTAR 0x18 /* Estar config register */ 61#define UPA_CFG_ESTAR_SPEED_FULL 0x01 62#define UPA_CFG_ESTAR_SPEED_1_2 0x02 63#define UPA_CFG_ESTAR_SPEED_1_64 0x40 64 65#define UPA_INO_BASE 0x2a 66#define UPA_INO_MAX 0x2b 67 68struct upa_regs { 69 uint64_t phys; 70 uint64_t size; 71}; 72 73struct upa_ranges { 74 uint64_t child; 75 uint64_t parent; 76 uint64_t size; 77}; 78 79struct upa_devinfo { 80 struct ofw_bus_devinfo udi_obdinfo; 81 struct resource_list udi_rl; 82}; 83 84struct upa_softc { 85 struct resource *sc_res[UPA_NREG]; 86 bus_space_tag_t sc_bt[UPA_NREG]; 87 bus_space_handle_t sc_bh[UPA_NREG]; 88 89 uint32_t sc_ign; 90 91 int sc_nrange; 92 struct upa_ranges *sc_ranges; 93}; 94 95#define UPA_READ(sc, reg, off) \ 96 bus_space_read_8((sc)->sc_bt[(reg)], (sc)->sc_bh[(reg)], (off)) 97#define UPA_WRITE(sc, reg, off, val) \ 98 bus_space_write_8((sc)->sc_bt[(reg)], (sc)->sc_bh[(reg)], (off), (val)) 99 100static device_probe_t upa_probe; 101static device_attach_t upa_attach; 102static bus_print_child_t upa_print_child; 103static bus_probe_nomatch_t upa_probe_nomatch; 104static bus_alloc_resource_t upa_alloc_resource; 105static bus_adjust_resource_t upa_adjust_resource; 106static bus_setup_intr_t upa_setup_intr; 107static bus_get_resource_list_t upa_get_resource_list; 108static ofw_bus_get_devinfo_t upa_get_devinfo; 109 110static void upa_intr_enable(void *); 111static void upa_intr_disable(void *); 112static void upa_intr_assign(void *); 113static struct upa_devinfo *upa_setup_dinfo(device_t, struct upa_softc *, 114 phandle_t, uint32_t); 115static void upa_destroy_dinfo(struct upa_devinfo *); 116static int upa_print_res(struct upa_devinfo *); 117 118static device_method_t upa_methods[] = { 119 /* Device interface */ 120 DEVMETHOD(device_probe, upa_probe), 121 DEVMETHOD(device_attach, upa_attach), 122 DEVMETHOD(device_shutdown, bus_generic_shutdown), 123 DEVMETHOD(device_suspend, bus_generic_suspend), 124 DEVMETHOD(device_resume, bus_generic_resume), 125 126 /* Bus interface */ 127 DEVMETHOD(bus_print_child, upa_print_child), 128 DEVMETHOD(bus_probe_nomatch, upa_probe_nomatch), 129 DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), 130 DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), 131 DEVMETHOD(bus_alloc_resource, upa_alloc_resource), 132 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 133 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 134 DEVMETHOD(bus_adjust_resource, upa_adjust_resource), 135 DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), 136 DEVMETHOD(bus_setup_intr, upa_setup_intr), 137 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 138 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 139 DEVMETHOD(bus_get_resource_list, upa_get_resource_list), 140 DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), 141 142 /* ofw_bus interface */ 143 DEVMETHOD(ofw_bus_get_devinfo, upa_get_devinfo), 144 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 145 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 146 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 147 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 148 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 149 150 DEVMETHOD_END 151}; 152 153static devclass_t upa_devclass; 154 155DEFINE_CLASS_0(upa, upa_driver, upa_methods, sizeof(struct upa_softc)); 156EARLY_DRIVER_MODULE(upa, nexus, upa_driver, upa_devclass, 0, 0, BUS_PASS_BUS); 157 158static const struct intr_controller upa_ic = { 159 upa_intr_enable, 160 upa_intr_disable, 161 upa_intr_assign, 162 /* The interrupts are pulse type and thus automatically cleared. */ 163 NULL 164}; 165 166struct upa_icarg { 167 struct upa_softc *uica_sc; 168 u_int uica_imr; 169}; 170 171static int 172upa_probe(device_t dev) 173{ 174 const char* compat; 175 176 compat = ofw_bus_get_compat(dev); 177 if (compat != NULL && strcmp(ofw_bus_get_name(dev), "upa") == 0 && 178 strcmp(compat, "upa64s") == 0) { 179 device_set_desc(dev, "UPA bridge"); 180 return (BUS_PROBE_DEFAULT); 181 } 182 return (ENXIO); 183} 184 185static int 186upa_attach(device_t dev) 187{ 188 struct upa_devinfo *udi; 189 struct upa_icarg *uica; 190 struct upa_softc *sc; 191 phandle_t child, node; 192 device_t cdev; 193 uint32_t portid; 194 int i, imr, j, rid; 195#if 1 196 device_t *children, schizo; 197 rman_res_t scount, sstart, ucount, ustart; 198 int nchildren; 199#endif 200 201 sc = device_get_softc(dev); 202 node = ofw_bus_get_node(dev); 203 for (i = UPA_CFG; i <= UPA_IMR2; i++) { 204 rid = i; 205 /* 206 * The UPA_IMR{1,2} resources are shared with that of the 207 * Schizo PCI bus B CSR bank. 208 */ 209#if 0 210 sc->sc_res[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 211 &rid, ((i == UPA_IMR1 || i == UPA_IMR2) ? RF_SHAREABLE : 212 0) | RF_ACTIVE); 213 if (sc->sc_res[i] == NULL) { 214 device_printf(dev, 215 "could not allocate resource %d\n", i); 216 goto fail; 217 } 218 sc->sc_bt[i] = rman_get_bustag(sc->sc_res[i]); 219 sc->sc_bh[i] = rman_get_bushandle(sc->sc_res[i]); 220#else 221 /* 222 * Workaround for the fact that rman(9) only allows to 223 * share resources of the same size. 224 */ 225 if (i == UPA_IMR1 || i == UPA_IMR2) { 226 if (bus_get_resource(dev, SYS_RES_MEMORY, i, &ustart, 227 &ucount) != 0) { 228 device_printf(dev, 229 "could not determine UPA resource\n"); 230 goto fail; 231 } 232 if (device_get_children(device_get_parent(dev), 233 &children, &nchildren) != 0) { 234 device_printf(dev, "could not get children\n"); 235 goto fail; 236 } 237 schizo = NULL; 238 for (j = 0; j < nchildren; j++) { 239 if (ofw_bus_get_type(children[j]) != NULL && 240 strcmp(ofw_bus_get_type(children[j]), 241 "pci") == 0 && 242 ofw_bus_get_compat(children[j]) != NULL && 243 strcmp(ofw_bus_get_compat(children[j]), 244 "pci108e,8001") == 0 && 245 ((bus_get_resource_start(children[j], 246 SYS_RES_MEMORY, 0) >> 20) & 1) == 1) { 247 schizo = children[j]; 248 break; 249 } 250 } 251 free(children, M_TEMP); 252 if (schizo == NULL) { 253 device_printf(dev, "could not find Schizo\n"); 254 goto fail; 255 } 256 if (bus_get_resource(schizo, SYS_RES_MEMORY, 0, 257 &sstart, &scount) != 0) { 258 device_printf(dev, 259 "could not determine Schizo resource\n"); 260 goto fail; 261 } 262 sc->sc_res[i] = bus_alloc_resource(dev, SYS_RES_MEMORY, 263 &rid, sstart, sstart + scount - 1, scount, 264 RF_SHAREABLE | RF_ACTIVE); 265 } else 266 sc->sc_res[i] = bus_alloc_resource_any(dev, 267 SYS_RES_MEMORY, &rid, RF_ACTIVE); 268 if (sc->sc_res[i] == NULL) { 269 device_printf(dev, 270 "could not allocate resource %d\n", i); 271 goto fail; 272 } 273 sc->sc_bt[i] = rman_get_bustag(sc->sc_res[i]); 274 sc->sc_bh[i] = rman_get_bushandle(sc->sc_res[i]); 275 if (i == UPA_IMR1 || i == UPA_IMR2) 276 bus_space_subregion(sc->sc_bt[i], sc->sc_bh[i], 277 ustart - sstart, ucount, &sc->sc_bh[i]); 278#endif 279 } 280 281 if (OF_getprop(node, "portid", &sc->sc_ign, sizeof(sc->sc_ign)) == -1) { 282 device_printf(dev, "could not determine IGN\n"); 283 goto fail; 284 } 285 286 sc->sc_nrange = OF_getprop_alloc(node, "ranges", sizeof(*sc->sc_ranges), 287 (void **)&sc->sc_ranges); 288 if (sc->sc_nrange == -1) { 289 device_printf(dev, "could not determine ranges\n"); 290 goto fail; 291 } 292 293 /* 294 * Hunt through all the interrupt mapping regs and register our 295 * interrupt controller for the corresponding interrupt vectors. 296 * We do this early in order to be able to catch stray interrupts. 297 */ 298 for (i = UPA_INO_BASE; i <= UPA_INO_MAX; i++) { 299 imr = 0; 300 for (j = UPA_IMR1; j <= UPA_IMR2; j++) { 301 if (INTVEC(UPA_READ(sc, j, 0x0)) == 302 INTMAP_VEC(sc->sc_ign, i)) { 303 imr = j; 304 break; 305 } 306 } 307 if (imr == 0) 308 continue; 309 uica = malloc(sizeof(*uica), M_DEVBUF, M_NOWAIT); 310 if (uica == NULL) 311 panic("%s: could not allocate interrupt controller " 312 "argument", __func__); 313 uica->uica_sc = sc; 314 uica->uica_imr = imr; 315#ifdef UPA_DEBUG 316 device_printf(dev, "intr map (INO %d) IMR%d: %#lx\n", 317 i, imr, (u_long)UPA_READ(sc, imr, 0x0)); 318#endif 319 j = intr_controller_register(INTMAP_VEC(sc->sc_ign, i), 320 &upa_ic, uica); 321 if (j != 0) 322 device_printf(dev, "could not register interrupt " 323 "controller for INO %d (%d)\n", i, j); 324 } 325 326 /* Make sure the power level is appropriate for normal operation. */ 327 if (UPA_READ(sc, UPA_CFG, UPA_CFG_IF) != UPA_CFG_IF_POK) { 328 if (bootverbose) 329 device_printf(dev, "applying power\n"); 330 UPA_WRITE(sc, UPA_CFG, UPA_CFG_ESTAR, UPA_CFG_ESTAR_SPEED_1_2); 331 UPA_WRITE(sc, UPA_CFG, UPA_CFG_ESTAR, UPA_CFG_ESTAR_SPEED_FULL); 332 (void)UPA_READ(sc, UPA_CFG, UPA_CFG_ESTAR); 333 UPA_WRITE(sc, UPA_CFG, UPA_CFG_IF, UPA_CFG_IF_POK_RST); 334 (void)UPA_READ(sc, UPA_CFG, UPA_CFG_IF); 335 DELAY(20000); 336 UPA_WRITE(sc, UPA_CFG, UPA_CFG_IF, UPA_CFG_IF_POK); 337 (void)UPA_READ(sc, UPA_CFG, UPA_CFG_IF); 338 } 339 340 for (child = OF_child(node); child != 0; child = OF_peer(child)) { 341 /* 342 * The `upa-portid' properties of the children are used as 343 * index for the interrupt mapping registers. 344 * The `upa-portid' properties are also used to make up the 345 * INOs of the children as the values contained in their 346 * `interrupts' properties are bogus. 347 */ 348 if (OF_getprop(child, "upa-portid", &portid, 349 sizeof(portid)) == -1) { 350 device_printf(dev, 351 "could not determine upa-portid of child 0x%lx\n", 352 (unsigned long)child); 353 continue; 354 } 355 if (portid > 1) { 356 device_printf(dev, 357 "upa-portid %d of child 0x%lx invalid\n", portid, 358 (unsigned long)child); 359 continue; 360 } 361 if ((udi = upa_setup_dinfo(dev, sc, child, portid)) == NULL) 362 continue; 363 if ((cdev = device_add_child(dev, NULL, -1)) == NULL) { 364 device_printf(dev, "<%s>: device_add_child failed\n", 365 udi->udi_obdinfo.obd_name); 366 upa_destroy_dinfo(udi); 367 continue; 368 } 369 device_set_ivars(cdev, udi); 370 } 371 372 return (bus_generic_attach(dev)); 373 374 fail: 375 for (i = UPA_CFG; i <= UPA_IMR2 && sc->sc_res[i] != NULL; i++) 376 bus_release_resource(dev, SYS_RES_MEMORY, 377 rman_get_rid(sc->sc_res[i]), sc->sc_res[i]); 378 return (ENXIO); 379} 380 381static int 382upa_print_child(device_t dev, device_t child) 383{ 384 int rv; 385 386 rv = bus_print_child_header(dev, child); 387 rv += upa_print_res(device_get_ivars(child)); 388 rv += bus_print_child_footer(dev, child); 389 return (rv); 390} 391 392static void 393upa_probe_nomatch(device_t dev, device_t child) 394{ 395 const char *type; 396 397 device_printf(dev, "<%s>", ofw_bus_get_name(child)); 398 upa_print_res(device_get_ivars(child)); 399 type = ofw_bus_get_type(child); 400 printf(" type %s (no driver attached)\n", 401 type != NULL ? type : "unknown"); 402} 403 404static struct resource * 405upa_alloc_resource(device_t dev, device_t child, int type, int *rid, 406 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 407{ 408 struct resource_list *rl; 409 struct resource_list_entry *rle; 410 struct upa_softc *sc; 411 struct resource *rv; 412 bus_addr_t cend, cstart; 413 int i, isdefault, passthrough; 414 415 isdefault = RMAN_IS_DEFAULT_RANGE(start, end); 416 passthrough = (device_get_parent(child) != dev); 417 sc = device_get_softc(dev); 418 rl = BUS_GET_RESOURCE_LIST(dev, child); 419 rle = NULL; 420 switch (type) { 421 case SYS_RES_IRQ: 422 return (resource_list_alloc(rl, dev, child, type, rid, start, 423 end, count, flags)); 424 case SYS_RES_MEMORY: 425 if (!passthrough) { 426 rle = resource_list_find(rl, type, *rid); 427 if (rle == NULL) 428 return (NULL); 429 if (rle->res != NULL) 430 panic("%s: resource entry is busy", __func__); 431 if (isdefault) { 432 start = rle->start; 433 count = ulmax(count, rle->count); 434 end = ulmax(rle->end, start + count - 1); 435 } 436 } 437 for (i = 0; i < sc->sc_nrange; i++) { 438 cstart = sc->sc_ranges[i].child; 439 cend = cstart + sc->sc_ranges[i].size - 1; 440 if (start < cstart || start > cend) 441 continue; 442 if (end < cstart || end > cend) 443 return (NULL); 444 start += sc->sc_ranges[i].parent - cstart; 445 end += sc->sc_ranges[i].parent - cstart; 446 rv = bus_generic_alloc_resource(dev, child, type, rid, 447 start, end, count, flags); 448 if (!passthrough) 449 rle->res = rv; 450 return (rv); 451 } 452 /* FALLTHROUGH */ 453 default: 454 return (NULL); 455 } 456} 457 458static void 459upa_intr_enable(void *arg) 460{ 461 struct intr_vector *iv = arg; 462 struct upa_icarg *uica = iv->iv_icarg; 463 464 UPA_WRITE(uica->uica_sc, uica->uica_imr, 0x0, 465 INTMAP_ENABLE(iv->iv_vec, iv->iv_mid)); 466 (void)UPA_READ(uica->uica_sc, uica->uica_imr, 0x0); 467} 468 469static void 470upa_intr_disable(void *arg) 471{ 472 struct intr_vector *iv = arg; 473 struct upa_icarg *uica = iv->iv_icarg; 474 475 UPA_WRITE(uica->uica_sc, uica->uica_imr, 0x0, iv->iv_vec); 476 (void)UPA_READ(uica->uica_sc, uica->uica_imr, 0x0); 477} 478 479static void 480upa_intr_assign(void *arg) 481{ 482 struct intr_vector *iv = arg; 483 struct upa_icarg *uica = iv->iv_icarg; 484 485 UPA_WRITE(uica->uica_sc, uica->uica_imr, 0x0, INTMAP_TID( 486 UPA_READ(uica->uica_sc, uica->uica_imr, 0x0), iv->iv_mid)); 487 (void)UPA_READ(uica->uica_sc, uica->uica_imr, 0x0); 488} 489 490static int 491upa_setup_intr(device_t dev, device_t child, struct resource *ires, int flags, 492 driver_filter_t *filt, driver_intr_t *func, void *arg, void **cookiep) 493{ 494 struct upa_softc *sc; 495 u_long vec; 496 497 sc = device_get_softc(dev); 498 /* 499 * Make sure the vector is fully specified and we registered 500 * our interrupt controller for it. 501 */ 502 vec = rman_get_start(ires); 503 if (INTIGN(vec) != sc->sc_ign || intr_vectors[vec].iv_ic != &upa_ic) { 504 device_printf(dev, "invalid interrupt vector 0x%lx\n", vec); 505 return (EINVAL); 506 } 507 return (bus_generic_setup_intr(dev, child, ires, flags, filt, func, 508 arg, cookiep)); 509} 510 511static int 512upa_adjust_resource(device_t bus __unused, device_t child __unused, 513 int type __unused, struct resource *r __unused, rman_res_t start __unused, 514 rman_res_t end __unused) 515{ 516 517 return (ENXIO); 518} 519 520static struct resource_list * 521upa_get_resource_list(device_t dev, device_t child) 522{ 523 struct upa_devinfo *udi; 524 525 udi = device_get_ivars(child); 526 return (&udi->udi_rl); 527} 528 529static const struct ofw_bus_devinfo * 530upa_get_devinfo(device_t dev, device_t child) 531{ 532 struct upa_devinfo *udi; 533 534 udi = device_get_ivars(child); 535 return (&udi->udi_obdinfo); 536} 537 538static struct upa_devinfo * 539upa_setup_dinfo(device_t dev, struct upa_softc *sc, phandle_t node, 540 uint32_t portid) 541{ 542 struct upa_devinfo *udi; 543 struct upa_regs *reg; 544 uint32_t intr; 545 int i, nreg; 546 547 udi = malloc(sizeof(*udi), M_DEVBUF, M_WAITOK | M_ZERO); 548 if (ofw_bus_gen_setup_devinfo(&udi->udi_obdinfo, node) != 0) { 549 free(udi, M_DEVBUF); 550 return (NULL); 551 } 552 resource_list_init(&udi->udi_rl); 553 554 nreg = OF_getprop_alloc(node, "reg", sizeof(*reg), (void **)®); 555 if (nreg == -1) { 556 device_printf(dev, "<%s>: incomplete\n", 557 udi->udi_obdinfo.obd_name); 558 goto fail; 559 } 560 for (i = 0; i < nreg; i++) 561 resource_list_add(&udi->udi_rl, SYS_RES_MEMORY, i, reg[i].phys, 562 reg[i].phys + reg[i].size - 1, reg[i].size); 563 free(reg, M_OFWPROP); 564 565 intr = INTMAP_VEC(sc->sc_ign, (UPA_INO_BASE + portid)); 566 resource_list_add(&udi->udi_rl, SYS_RES_IRQ, 0, intr, intr, 1); 567 568 return (udi); 569 570 fail: 571 upa_destroy_dinfo(udi); 572 return (NULL); 573} 574 575static void 576upa_destroy_dinfo(struct upa_devinfo *dinfo) 577{ 578 579 resource_list_free(&dinfo->udi_rl); 580 ofw_bus_gen_destroy_devinfo(&dinfo->udi_obdinfo); 581 free(dinfo, M_DEVBUF); 582} 583 584static int 585upa_print_res(struct upa_devinfo *udi) 586{ 587 int rv; 588 589 rv = 0; 590 rv += resource_list_print_type(&udi->udi_rl, "mem", SYS_RES_MEMORY, 591 "%#lx"); 592 rv += resource_list_print_type(&udi->udi_rl, "irq", SYS_RES_IRQ, 593 "%ld"); 594 return (rv); 595} 596