1 /* $NetBSD: pci_machdep.c,v 1.23 2025/10/04 15:34:52 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1999, 2000 Matthew R. Green 5 * Copyright (c) 2001 Valeriy E. Ushakov 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 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 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /* 33 * Machine-dependent PCI bits for PCI controller in microSPARC-IIep. 34 * References are to the microSPARC-IIep manual unless noted otherwise. 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.23 2025/10/04 15:34:52 thorpej Exp $"); 39 40 #if defined(DEBUG) && !defined(SPARC_PCI_DEBUG) 41 #define SPARC_PCI_DEBUG 42 #endif 43 44 #ifdef SPARC_PCI_DEBUG 45 #define SPDB_CONF 0x01 46 #define SPDB_INTR 0x04 47 #define SPDB_INTMAP 0x08 48 #define SPDB_INTFIX 0x10 49 #define SPDB_PROBE 0x20 50 int sparc_pci_debug = 0; 51 #define DPRINTF(l, s) do { \ 52 if (sparc_pci_debug & (l)) \ 53 printf s; \ 54 } while (/* CONSTCOND */ 0) 55 #else 56 #define DPRINTF(l, s) 57 #endif 58 59 #include <sys/types.h> 60 #include <sys/param.h> 61 #include <sys/time.h> 62 #include <sys/systm.h> 63 #include <sys/errno.h> 64 #include <sys/device.h> 65 66 #include <sys/bus.h> 67 #include <machine/autoconf.h> 68 69 #include <machine/ctlreg.h> 70 #include <sparc/sparc/asm.h> 71 72 #include <dev/pci/pcivar.h> 73 #include <dev/pci/pcireg.h> 74 #include <dev/pci/pci_calls.h> 75 76 #include <dev/ofw/ofw_pci.h> 77 78 #include <sparc/sparc/msiiepreg.h> 79 #include <sparc/sparc/msiiepvar.h> 80 81 /* 82 * Table 9-1 (p. 129). 83 * Configuration space access. This goes via MMU bypass ASI. 84 */ 85 #define PCI_MODE1_ADDRESS_REG_PA 0x30080000 86 #define PCI_MODE1_DATA_REG_PA 0x300a0000 87 88 /* 89 * Footnote 1 in Table 9-1 (p. 129): 90 * 91 * Three least significant bits of the configuration data space 92 * access must match those of the configuration address space access. 93 */ 94 #define PCI_MODE1_DATA_REG_MASK 0x7 95 96 97 /* 98 * PROMs in ms-IIep systems just lie about PCI and EBus interrupts, so 99 * we just hardcode the wiring based on the model we are running on. 100 * Probably we can do some forth hacking in boot loader's prompatch 101 * (that's what it was introduced for), but for now it's way more 102 * simple to just hardcode it here. 103 * XXX: Unknown mappings for PCI slots set to line 8. 104 */ 105 106 struct mspcic_pci_intr_wiring { 107 u_int mpiw_bus; 108 u_int mpiw_device; 109 u_int mpiw_function; 110 pci_intr_line_t mpiw_line[4]; /* Int A (0) - Int D (3) */ 111 }; 112 113 static struct mspcic_pci_intr_wiring krups_pci_intr_wiring[] = { 114 { 0, 0, 1, { 1, 0, 0, 0 } }, /* ethernet */ 115 { 0, 1, 0, { 2, 0, 0, 0 } }, /* vga */ 116 }; 117 118 static struct mspcic_pci_intr_wiring espresso_pci_intr_wiring[] = { 119 { 0, 0, 1, { 1, 0, 0, 0 } }, /* ethernet */ 120 { 0, 1, 0, { 2, 0, 0, 0 } }, /* vga */ 121 { 0, 2, 0, { 6, 7, 8, 8 } }, /* pci slot1 */ 122 { 0, 2, 1, { 6, 7, 8, 8 } }, /* pci slot1 */ 123 { 0, 2, 2, { 6, 7, 8, 8 } }, /* pci slot1 */ 124 { 0, 2, 3, { 6, 7, 8, 8 } }, /* pci slot1 */ 125 { 0, 2, 4, { 6, 7, 8, 8 } }, /* pci slot1 */ 126 { 0, 2, 5, { 6, 7, 8, 8 } }, /* pci slot1 */ 127 { 0, 2, 6, { 6, 7, 8, 8 } }, /* pci slot1 */ 128 { 0, 2, 7, { 6, 7, 8, 8 } }, /* pci slot1 */ 129 { 0, 3, 0, { 7, 8, 8, 8 } }, /* pci slot2 */ 130 { 0, 3, 1, { 7, 8, 8, 8 } }, /* pci slot2 */ 131 { 0, 3, 2, { 7, 8, 8, 8 } }, /* pci slot2 */ 132 { 0, 3, 3, { 7, 8, 8, 8 } }, /* pci slot2 */ 133 { 0, 3, 4, { 7, 8, 8, 8 } }, /* pci slot2 */ 134 { 0, 3, 5, { 7, 8, 8, 8 } }, /* pci slot2 */ 135 { 0, 3, 6, { 7, 8, 8, 8 } }, /* pci slot2 */ 136 { 0, 3, 7, { 7, 8, 8, 8 } }, /* pci slot2 */ 137 { 0, 7, 0, { 4, 0, 0, 0 } }, /* isa */ 138 { 0, 16, 0, { 5, 0, 0, 0 } }, /* eide */ 139 { 0, 20, 0, { 5, 0, 0, 0 } }, /* usb */ 140 }; 141 142 struct mspcic_known_model { 143 const char *model; 144 struct mspcic_pci_intr_wiring *map; 145 int mapsize; 146 }; 147 148 #define MSPCIC_MODEL_WIRING(name,map) \ 149 { name, map, sizeof(map)/sizeof(map[0]) } 150 151 static struct mspcic_known_model mspcic_known_models[] = { 152 MSPCIC_MODEL_WIRING("SUNW,501-4267", krups_pci_intr_wiring), 153 MSPCIC_MODEL_WIRING("SUNW,375-0059", espresso_pci_intr_wiring), 154 { NULL, NULL, 0} 155 }; 156 157 158 static struct mspcic_pci_intr_wiring *wiring_map; 159 static int wiring_map_size; 160 161 static int 162 sparc_pci_bus_get_child_devhandle(device_t dev, devhandle_t call_handle, 163 void *v) 164 { 165 struct pci_bus_get_child_devhandle_args *args = v; 166 167 /* 168 * We've already gone through the trouble of encoding the 169 * PROM node into the pcitag_t. 170 */ 171 int node = PCITAG_NODE(args->tag); 172 if (node != -1) { 173 args->devhandle = prom_node_to_devhandle(call_handle, node); 174 return 0; 175 } 176 177 return ENODEV; 178 } 179 OBP_DEVICE_CALL_REGISTER(PCI_BUS_GET_CHILD_DEVHANDLE_STR, 180 sparc_pci_bus_get_child_devhandle) 181 182 void 183 pci_attach_hook(device_t parent, device_t self, 184 struct pcibus_attach_args *pba) 185 { 186 struct mspcic_known_model *p; 187 char buf[32]; 188 char *model; 189 190 /* We only need to run once (root PCI bus is 0) */ 191 if (pba->pba_bus != 0) 192 return; 193 194 model = prom_getpropstringA(prom_findroot(), "model", 195 buf, sizeof(buf)); 196 if (model == NULL) 197 panic("pci_attach_hook: no \"model\" property"); 198 199 printf(": model %s", model); 200 201 for (p = mspcic_known_models; p->model != NULL; ++p) 202 if (strcmp(model, p->model) == 0) { 203 printf(": interrupt wiring known"); 204 wiring_map = p->map; 205 wiring_map_size = p->mapsize; 206 return; 207 } 208 209 /* not found */ 210 printf(": don't know how interrupts are wired\n"); 211 panic("pci_attach_hook: unknown model %s", model); 212 } 213 214 215 int 216 pci_bus_maxdevs(pci_chipset_tag_t pc, int busno) 217 { 218 219 return 32; 220 } 221 222 223 pcitag_t 224 pci_make_tag(pci_chipset_tag_t pc, int b, int d, int f) 225 { 226 struct mspcic_softc *sc = (struct mspcic_softc *)pc->cookie; 227 pcitag_t tag; 228 int node, len; 229 #ifdef SPARC_PCI_DEBUG 230 char name[80]; 231 232 memset(name, 0, sizeof(name)); 233 #endif 234 tag = PCITAG_CREATE(-1, b, d, f); 235 if (b >= 256 || d >= 32 || f >= 8) { 236 printf("pci_make_tag: bad request %d/%d/%d\n", b, d, f); 237 return tag; /* a dead one */ 238 } 239 240 /* 241 * XXX: OFW 3.11 doesn't have "bus-range" property on its 242 * "/pci" node. As a workaround we start with the first child 243 * of "/pci" instead of matching the bus number against the 244 * "bus-range" of the "/pci" node. 245 * 246 * Traverse all peers until we find the node. 247 */ 248 for (node = OF_child(sc->sc_node); node != 0; node = OF_peer(node)) { 249 struct ofw_pci_register reg; 250 uint32_t busrange[2]; 251 int class; 252 pcireg_t busdata; 253 pcitag_t bustag; 254 255 #ifdef SPARC_PCI_DEBUG 256 if (sparc_pci_debug & SPDB_PROBE) { 257 OF_getprop(node, "name", &name, sizeof(name)); 258 printf("> checking node %x %s\n", node, name); 259 } 260 #endif 261 /* 262 * Check for PCI-PCI bridges. If the device we want is 263 * in the bus-range for that bridge, work our way down. 264 */ 265 while ((OF_getprop(node, "bus-range", (void *)&busrange, 266 sizeof(busrange)) == sizeof(busrange)) 267 && (b >= busrange[0] && b <= busrange[1])) 268 { 269 /* go down one level */ 270 node = OF_child(node); 271 #ifdef SPARC_PCI_DEBUG 272 if (sparc_pci_debug & SPDB_PROBE) { 273 OF_getprop(node, "name", &name, sizeof(name)); 274 printf("> going down to node %x %s\n", 275 node, name); 276 } 277 #endif 278 } 279 280 /* 281 * We only really need the first `reg' property. 282 * 283 * For simplicity, we'll query the `reg' when we 284 * need it. Otherwise we could malloc() it, but 285 * that gets more complicated. 286 */ 287 len = OF_getproplen(node, "reg"); 288 OF_getprop(node, "reg", (void *)®, sizeof(reg)); 289 290 /* 291 * Check for (OFW unconfigured) bridges that we fixed up. 292 * We'll set this top-level bridge's node in the tag, 293 * so that we can use it later for interrupt wiring. 294 */ 295 if (b > 0) { 296 len = OF_getproplen(node, "class-code"); 297 if (!len) 298 continue; 299 OF_getprop(node, "class-code", &class, len); 300 if (IS_PCI_BRIDGE(class)) { 301 bustag = PCITAG_CREATE(node, 302 OFW_PCI_PHYS_HI_BUS(reg.phys_hi), 303 OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi), 304 OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi)); 305 busdata = pci_conf_read(NULL, bustag, 306 PCI_BRIDGE_BUS_REG); 307 if (b != ((busdata >> 8) & 0xff)) 308 continue; 309 310 #ifdef SPARC_PCI_DEBUG 311 if (sparc_pci_debug & SPDB_PROBE) { 312 OF_getprop(node, "name", &name, 313 sizeof(name)); 314 printf("> matched device behind node " 315 "%x %s (bus %d)\n", node, name, b); 316 } 317 #endif 318 } else 319 continue; 320 } else { 321 if (b != OFW_PCI_PHYS_HI_BUS(reg.phys_hi)) 322 continue; 323 if (d != OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi)) 324 continue; 325 if (f != OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi)) 326 continue; 327 } 328 329 /* Got a match */ 330 tag = PCITAG_CREATE(node, b, d, f); 331 DPRINTF(SPDB_PROBE, ("> found node %x %s\n", node, name)); 332 return tag; 333 } 334 335 /* No device found - return a dead tag */ 336 return tag; 337 } 338 339 340 void 341 pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, 342 int *bp, int *dp, int *fp) 343 { 344 345 if (bp != NULL) 346 *bp = PCITAG_BUS(tag); 347 if (dp != NULL) 348 *dp = PCITAG_DEV(tag); 349 if (fp != NULL) 350 *fp = PCITAG_FUN(tag); 351 } 352 353 354 pcireg_t 355 pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) 356 { 357 uint32_t mode1_addr; 358 uint32_t mode1_data_reg_pa; 359 uint32_t val; 360 361 DPRINTF(SPDB_CONF, 362 ("pci_conf_read: tag=%x.%x (%d/%d/%d), reg=%02x; ", 363 PCITAG_NODE(tag), PCITAG_OFFSET(tag), 364 PCITAG_BUS(tag), PCITAG_DEV(tag), PCITAG_FUN(tag), 365 reg)); 366 367 #ifdef DIAGNOSTIC 368 if (reg & 0x3) 369 panic("pci_conf_read: reg %x unaligned", reg); 370 #endif 371 372 if (PCITAG_NODE(tag) == -1) { 373 DPRINTF(SPDB_CONF, ("\n")); 374 return ~0; 375 } 376 377 if ((unsigned int)reg >= PCI_CONF_SIZE) 378 return ~0; 379 380 mode1_addr = PCITAG_OFFSET(tag) | reg; 381 mode1_data_reg_pa = PCI_MODE1_DATA_REG_PA 382 | (reg & PCI_MODE1_DATA_REG_MASK); 383 384 sta(PCI_MODE1_ADDRESS_REG_PA, ASI_BYPASS, htole32(mode1_addr)); 385 val = le32toh(lda(mode1_data_reg_pa, ASI_BYPASS)); 386 387 DPRINTF(SPDB_CONF, ("reading %08x\n", val)); 388 389 return val; 390 } 391 392 393 void 394 pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) 395 { 396 uint32_t mode1_addr; 397 uint32_t mode1_data_reg_pa; 398 399 DPRINTF(SPDB_CONF, 400 ("pci_conf_write: tag=%x.%x (%d/%d/%d); reg=%02x; ", 401 PCITAG_NODE(tag), PCITAG_OFFSET(tag), 402 PCITAG_BUS(tag), PCITAG_DEV(tag), PCITAG_FUN(tag), 403 reg)); 404 405 #ifdef DIAGNOSTIC 406 if (reg & 0x3) 407 panic("pci_conf_write: reg %x unaligned", reg); 408 #endif 409 410 if (PCITAG_NODE(tag) == -1) { 411 DPRINTF(SPDB_CONF, ("\n")); 412 return; 413 } 414 415 if ((unsigned int)reg >= PCI_CONF_SIZE) 416 return; 417 418 mode1_addr = PCITAG_OFFSET(tag) | reg; 419 mode1_data_reg_pa = PCI_MODE1_DATA_REG_PA 420 | (reg & PCI_MODE1_DATA_REG_MASK); 421 422 DPRINTF(SPDB_CONF, ("writing %08x\n", data)); 423 424 sta(PCI_MODE1_ADDRESS_REG_PA, ASI_BYPASS, htole32(mode1_addr)); 425 sta(mode1_data_reg_pa, ASI_BYPASS, htole32(data)); 426 } 427 428 429 /* ====================================================================== 430 * 431 * PCI bus interrupt manipulation functions 432 */ 433 434 int 435 pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) 436 { 437 int i, node; 438 pcitag_t tag; 439 pcireg_t val; 440 pci_intr_pin_t pin; 441 442 DPRINTF(SPDB_INTMAP, 443 ("pci_intr_map(%d/%d/%d) -> ", 444 pa->pa_bus, pa->pa_device, pa->pa_function)); 445 446 tag = pci_make_tag(pa->pa_pc, pa->pa_bus, pa->pa_device, 447 pa->pa_function); 448 node = PCITAG_NODE(tag); 449 val = pci_conf_read(NULL, tag, PCI_INTERRUPT_REG); 450 pin = PCI_INTERRUPT_PIN(val); 451 452 /* 453 * Pin should be A(1) to D(4) - use values 0 to 3 respectively to 454 * represent them. Built-in devices might show pin 0, so assume 455 * pin A for those - the static wiring map has the correct line. 456 */ 457 if (pin) 458 pin -= 1; 459 460 for (i = 0; i < wiring_map_size; ++i) { 461 struct mspcic_pci_intr_wiring *w = &wiring_map[i]; 462 463 /* Device on PCI bus 0 */ 464 if (pa->pa_bus == w->mpiw_bus 465 && pa->pa_device == w->mpiw_device 466 && pa->pa_function == w->mpiw_function) 467 { 468 if (w->mpiw_line[pin] > 7) { 469 DPRINTF(SPDB_INTMAP, ("not mapped\n")); 470 return -1; 471 } 472 DPRINTF(SPDB_INTMAP, ("pin %c line %d\n", 'A' + pin, 473 w->mpiw_line[pin])); 474 *ihp = w->mpiw_line[pin]; 475 return 0; 476 /* Device on other PCI bus - find top-level bridge device */ 477 } else if (pa->pa_bus) { 478 struct ofw_pci_register reg; 479 480 OF_getprop(node, "reg", (void *)®, sizeof(reg)); 481 if (OFW_PCI_PHYS_HI_BUS(reg.phys_hi) == w->mpiw_bus 482 && OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi) 483 == w->mpiw_device 484 && OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi) 485 == w->mpiw_function) { 486 int j; 487 488 /* PCI bridge interrupt swizzle */ 489 for (j = 0; j < PCI_INTERRUPT_LINE(val); j++) 490 pin = (pin + (pa->pa_device % 4)) % 4; 491 492 if (w->mpiw_line[pin] > 7) { 493 DPRINTF(SPDB_INTMAP, ("pin %c " 494 "not mapped\n", pin)); 495 return -1; 496 } 497 DPRINTF(SPDB_INTMAP, ("pin %c line %d " 498 "via bridge (%d/%d/%d) depth %d\n", 499 'A' + pin, w->mpiw_line[pin], 500 w->mpiw_bus, w->mpiw_device, 501 w->mpiw_function, 502 PCI_INTERRUPT_LINE(val))); 503 *ihp = w->mpiw_line[pin]; 504 return 0; 505 } 506 } 507 } 508 509 DPRINTF(SPDB_INTMAP, ("not found\n")); 510 return -1; 511 } 512 513 514 const char * 515 pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih, char *buf, 516 size_t len) 517 { 518 int pil; 519 520 pil = mspcic_assigned_interrupt(ih); 521 snprintf(buf, len, "line %d (pil %d)", ih, pil); 522 return buf; 523 } 524 525 526 const struct evcnt * 527 pci_intr_evcnt(pci_chipset_tag_t pc, pci_intr_handle_t ih) 528 { 529 530 /* XXX for now, no evcnt parent reported */ 531 return NULL; 532 } 533 534 int 535 pci_intr_setattr(pci_chipset_tag_t pc, pci_intr_handle_t *ih, 536 int attr, uint64_t data) 537 { 538 539 switch (attr) { 540 case PCI_INTR_MPSAFE: 541 return 0; 542 default: 543 return ENODEV; 544 } 545 } 546 547 void * 548 pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, 549 int level, int (*func)(void *), void *arg) 550 { 551 struct mspcic_softc *sc = (struct mspcic_softc *)pc->cookie; 552 void *cookie; 553 554 DPRINTF(SPDB_INTR, 555 ("pci_intr_establish(line %d, ipl %d)\n", ih, level)); 556 557 cookie = bus_intr_establish(sc->sc_memt, ih, level, func, arg); 558 559 /* 560 * TODO: to implement pci_intr_disestablish we need to capture 561 * the 'intrhand' returned by bus_intr_establish above and the 562 * pil the handler was established for, but we don't need to 563 * disestablish pci interrupts for now (and I doubt we will), 564 * so why bother. 565 */ 566 567 DPRINTF(SPDB_INTR, 568 ("pci_intr_establish: returning handle %p\n", cookie)); 569 return cookie; 570 } 571 572 573 void 574 pci_intr_disestablish(pci_chipset_tag_t pc, void *cookie) 575 { 576 577 DPRINTF(SPDB_INTR, ("pci_intr_disestablish: cookie %p\n", cookie)); 578 panic("pci_intr_disestablish: not implemented"); 579 } 580