1 /* $NetBSD: pci_machdep.c,v 1.5 2002/05/16 01:33:53 uwe 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 #if defined(DEBUG) && !defined(SPARC_PCI_DEBUG) 38 #define SPARC_PCI_DEBUG 39 #endif 40 41 #ifdef SPARC_PCI_DEBUG 42 #define SPDB_CONF 0x01 43 #define SPDB_INTR 0x04 44 #define SPDB_INTMAP 0x08 45 #define SPDB_INTFIX 0x10 46 #define SPDB_PROBE 0x20 47 int sparc_pci_debug = 0; 48 #define DPRINTF(l, s) do { \ 49 if (sparc_pci_debug & (l)) \ 50 printf s; \ 51 } while (/* CONSTCOND */ 0) 52 #else 53 #define DPRINTF(l, s) 54 #endif 55 56 #include <sys/types.h> 57 #include <sys/param.h> 58 #include <sys/time.h> 59 #include <sys/systm.h> 60 #include <sys/errno.h> 61 #include <sys/device.h> 62 #include <sys/malloc.h> 63 64 #include <machine/bus.h> 65 #include <machine/autoconf.h> 66 #include <machine/openfirm.h> 67 68 #include <machine/ctlreg.h> 69 #include <sparc/sparc/asm.h> 70 71 #include <dev/pci/pcivar.h> 72 #include <dev/pci/pcireg.h> 73 74 #include <dev/ofw/ofw_pci.h> 75 76 #include <sparc/sparc/msiiepreg.h> 77 #include <sparc/sparc/msiiepvar.h> 78 79 /* 80 * Table 9-1 (p. 129). 81 * Configuration space access. This goes via MMU bypass ASI. 82 */ 83 #define PCI_MODE1_ADDRESS_REG_PA 0x30080000 84 #define PCI_MODE1_DATA_REG_PA 0x300a0000 85 86 /* 87 * Footnote 1 in Table 9-1 (p. 129): 88 * 89 * Three least significant bits of the configuration data space 90 * access must match those of the configuration address space access. 91 */ 92 #define PCI_MODE1_DATA_REG_MASK 0x7 93 94 95 /* 96 * PROMs in ms-IIep systems just lie about PCI and EBus interrupts, so 97 * we just hardcode the wiring based on the model we are running on. 98 * Probably we can do some forth hacking in boot loader's prompatch 99 * (that's what it was introduced for), but for now it's way more 100 * simple to just hardcode it here. 101 */ 102 103 104 struct mspcic_pci_intr_wiring { 105 u_int mpiw_bus; 106 u_int mpiw_device; 107 u_int mpiw_function; 108 pci_intr_line_t mpiw_line; 109 }; 110 111 static struct mspcic_pci_intr_wiring krups_pci_intr_wiring[] = { 112 { 0, 0, 1, 1 }, /* ethernet */ 113 { 0, 1, 0, 2 }, /* vga */ 114 }; 115 116 117 struct mspcic_known_model { 118 const char *model; 119 struct mspcic_pci_intr_wiring *map; 120 int mapsize; 121 }; 122 123 #define MSPCIC_MODEL_WIRING(name,map) \ 124 { name, map, sizeof(map)/sizeof(map[0]) } 125 126 static struct mspcic_known_model mspcic_known_models[] = { 127 MSPCIC_MODEL_WIRING("SUNW,501-4267", krups_pci_intr_wiring), 128 { NULL, NULL, 0} 129 }; 130 131 132 static struct mspcic_pci_intr_wiring *wiring_map; 133 static int wiring_map_size; 134 135 136 void 137 pci_attach_hook(parent, self, pba) 138 struct device *parent; 139 struct device *self; 140 struct pcibus_attach_args *pba; 141 { 142 struct mspcic_known_model *p; 143 char buf[32]; 144 char *model; 145 146 model = PROM_getpropstringA(prom_findroot(), "model", 147 buf, sizeof(buf)); 148 if (model == NULL) 149 panic("pci_attach_hook: no \"model\" property"); 150 151 printf(": model %s", model); 152 153 for (p = mspcic_known_models; p->model != NULL; ++p) 154 if (strcmp(model, p->model) == 0) { 155 printf(": interrupt wiring known"); 156 wiring_map = p->map; 157 wiring_map_size = p->mapsize; 158 return; 159 } 160 161 /* not found */ 162 printf(": don't know how interrupts are wired\n"); 163 panic("pci_attach_hook: unknown model %s", model); 164 } 165 166 167 int 168 pci_bus_maxdevs(pc, busno) 169 pci_chipset_tag_t pc; 170 int busno; 171 { 172 173 return (32); 174 } 175 176 177 pcitag_t 178 pci_make_tag(pc, b, d, f) 179 pci_chipset_tag_t pc; 180 int b; 181 int d; 182 int f; 183 { 184 struct mspcic_softc *sc = (struct mspcic_softc *)pc->cookie; 185 pcitag_t tag; 186 int node, len; 187 #ifdef SPARC_PCI_DEBUG 188 char name[80]; 189 190 memset(name, 0, sizeof(name)); 191 #endif 192 193 tag = PCITAG_CREATE(-1, b, d, f); 194 if (b >= 256 || d >= 32 || f >= 8) { 195 printf("pci_make_tag: bad request %d/%d/%d\n", b, d, f); 196 return (tag); /* a dead one */ 197 } 198 199 /* 200 * XXX: OFW 3.11 doesn't have "bus-range" property on its 201 * "/pci" node. As a workaround we start with the first child 202 * of "/pci" instead of matching the bus number against the 203 * "bus-range" of the "/pci" node. 204 * 205 * Traverse all peers until we find the node. 206 */ 207 for (node = OF_child(sc->sc_node); node != 0; node = OF_peer(node)) { 208 struct ofw_pci_register reg; 209 u_int32_t busrange[2]; 210 211 #ifdef SPARC_PCI_DEBUG 212 if (sparc_pci_debug & SPDB_PROBE) { 213 OF_getprop(node, "name", &name, sizeof(name)); 214 printf("> checking node %x %s\n", node, name); 215 } 216 #endif 217 /* 218 * Check for PCI-PCI bridges. If the device we want is 219 * in the bus-range for that bridge, work our way down. 220 */ 221 while ((OF_getprop(node, "bus-range", (void *)&busrange, 222 sizeof(busrange)) == sizeof(busrange)) 223 && (b >= busrange[0] && b <= busrange[1])) 224 { 225 /* go down one level */ 226 node = OF_child(node); 227 #ifdef SPARC_PCI_DEBUG 228 if (sparc_pci_debug & SPDB_PROBE) { 229 OF_getprop(node, "name", &name, sizeof(name)); 230 printf("> going down to node %x %s\n", 231 node, name); 232 } 233 #endif 234 } 235 236 /* 237 * We only really need the first `reg' property. 238 * 239 * For simplicity, we'll query the `reg' when we 240 * need it. Otherwise we could malloc() it, but 241 * that gets more complicated. 242 */ 243 len = OF_getproplen(node, "reg"); 244 if (len < sizeof(reg)) 245 continue; 246 if (OF_getprop(node, "reg", (void *)®, sizeof(reg)) != len) 247 panic("pci_probe_bus: OF_getprop len botch"); 248 249 if (b != OFW_PCI_PHYS_HI_BUS(reg.phys_hi)) 250 continue; 251 if (d != OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi)) 252 continue; 253 if (f != OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi)) 254 continue; 255 256 /* Got a match */ 257 tag = PCITAG_CREATE(node, b, d, f); 258 259 /* Enable all the different spaces for this device */ 260 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, 261 PCI_COMMAND_MASTER_ENABLE 262 | PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_IO_ENABLE); 263 DPRINTF(SPDB_PROBE, ("> found node %x %s\n", node, name)); 264 return (tag); 265 } 266 267 /* No device found - return a dead tag */ 268 return (tag); 269 } 270 271 272 void 273 pci_decompose_tag(pc, tag, bp, dp, fp) 274 pci_chipset_tag_t pc; 275 pcitag_t tag; 276 int *bp, *dp, *fp; 277 { 278 if (bp != NULL) 279 *bp = PCITAG_BUS(tag); 280 if (dp != NULL) 281 *dp = PCITAG_DEV(tag); 282 if (fp != NULL) 283 *fp = PCITAG_FUN(tag); 284 } 285 286 287 pcireg_t 288 pci_conf_read(pc, tag, reg) 289 pci_chipset_tag_t pc; 290 pcitag_t tag; 291 int reg; 292 { 293 u_int32_t mode1_addr; 294 u_int32_t mode1_data_reg_pa; 295 pcireg_t val = (pcireg_t)~0; 296 297 DPRINTF(SPDB_CONF, 298 ("pci_conf_read: tag=%x.%x (%d/%d/%d), reg=%02x; ", 299 PCITAG_NODE(tag), PCITAG_OFFSET(tag), 300 PCITAG_BUS(tag), PCITAG_DEV(tag), PCITAG_FUN(tag), 301 reg)); 302 303 #ifdef DIAGNOSTIC 304 if (reg & 0x3) 305 panic("pci_conf_read: reg %x unaligned", reg); 306 if (reg & ~0xff) 307 panic("pci_conf_read: reg %x out of range", reg); 308 #endif 309 310 if (PCITAG_NODE(tag) == -1) { 311 DPRINTF(SPDB_CONF, ("\n")); 312 return (val); 313 } 314 315 mode1_addr = PCITAG_OFFSET(tag) | reg; 316 mode1_data_reg_pa = PCI_MODE1_DATA_REG_PA 317 | (reg & PCI_MODE1_DATA_REG_MASK); 318 319 /* 320 * NB: we run in endian-swapping mode, so we don't need to 321 * convert mode1_addr and val. 322 */ 323 sta(PCI_MODE1_ADDRESS_REG_PA, ASI_BYPASS, mode1_addr); 324 val = lda(mode1_data_reg_pa, ASI_BYPASS); 325 326 DPRINTF(SPDB_CONF, ("reading %08x\n", (u_int)val)); 327 328 return (val); 329 } 330 331 332 void 333 pci_conf_write(pc, tag, reg, data) 334 pci_chipset_tag_t pc; 335 pcitag_t tag; 336 int reg; 337 pcireg_t data; 338 { 339 u_int32_t mode1_addr; 340 u_int32_t mode1_data_reg_pa; 341 342 DPRINTF(SPDB_CONF, 343 ("pci_conf_write: tag=%x.%x (%d/%d/%d); reg=%02x; ", 344 PCITAG_NODE(tag), PCITAG_OFFSET(tag), 345 PCITAG_BUS(tag), PCITAG_DEV(tag), PCITAG_FUN(tag), 346 reg)); 347 348 #ifdef DIAGNOSTIC 349 if (reg & 0x3) 350 panic("pci_conf_write: reg %x unaligned", reg); 351 if (reg & ~0xff) 352 panic("pci_conf_write: reg %x out of range", reg); 353 #endif 354 355 if (PCITAG_NODE(tag) == -1) { 356 DPRINTF(SPDB_CONF, ("\n")); 357 return; 358 } 359 360 mode1_addr = PCITAG_OFFSET(tag) | reg; 361 mode1_data_reg_pa = PCI_MODE1_DATA_REG_PA 362 | (reg & PCI_MODE1_DATA_REG_MASK); 363 364 DPRINTF(SPDB_CONF, ("writing %08x\n", data)); 365 366 /* 367 * NB: we run in endian-swapping mode, so we don't need to 368 * convert mode1_addr and data. 369 */ 370 sta(PCI_MODE1_ADDRESS_REG_PA, ASI_BYPASS, mode1_addr); 371 sta(mode1_data_reg_pa, ASI_BYPASS, data); 372 } 373 374 375 /* ====================================================================== 376 * 377 * PCI bus interrupt manipulation functions 378 */ 379 380 int 381 pci_intr_map(pa, ihp) 382 struct pci_attach_args *pa; 383 pci_intr_handle_t *ihp; 384 { 385 int i; 386 387 DPRINTF(SPDB_INTMAP, 388 ("pci_intr_map(%d/%d/%d) -> ", 389 pa->pa_bus, pa->pa_device, pa->pa_function)); 390 391 for (i = 0; i < wiring_map_size; ++i) { 392 struct mspcic_pci_intr_wiring *w = &wiring_map[i]; 393 394 if (pa->pa_bus == w->mpiw_bus 395 && pa->pa_device == w->mpiw_device 396 && pa->pa_function == w->mpiw_function) 397 { 398 DPRINTF(SPDB_INTMAP, ("line %d\n", w->mpiw_line)); 399 *ihp = w->mpiw_line; 400 return (0); 401 } 402 } 403 404 DPRINTF(SPDB_INTMAP, ("not found\n")); 405 return (-1); 406 } 407 408 409 const char * 410 pci_intr_string(pc, ih) 411 pci_chipset_tag_t pc; 412 pci_intr_handle_t ih; 413 { 414 static char str[16]; 415 int pil; 416 417 pil = mspcic_assigned_interrupt(ih); 418 sprintf(str, "line %d (pil %d)", ih, pil); 419 return (str); 420 } 421 422 423 const struct evcnt * 424 pci_intr_evcnt(pc, ih) 425 pci_chipset_tag_t pc; 426 pci_intr_handle_t ih; 427 { 428 429 /* XXX for now, no evcnt parent reported */ 430 return NULL; 431 } 432 433 434 void * 435 pci_intr_establish(pc, ih, level, func, arg) 436 pci_chipset_tag_t pc; 437 pci_intr_handle_t ih; 438 int level; 439 int (*func)(void *); 440 void *arg; 441 { 442 struct mspcic_softc *sc = (struct mspcic_softc *)pc->cookie; 443 void *cookie = NULL; 444 445 DPRINTF(SPDB_INTR, 446 ("pci_intr_establish(line %d, ipl %d)\n", ih, level)); 447 448 cookie = bus_intr_establish(sc->sc_memt, ih, level, 0, func, arg); 449 450 /* 451 * TODO: to implement pci_intr_disestablish we need to capture 452 * the 'intrhand' returned by bus_intr_establish above and the 453 * pil the handler was established for, but we don't need to 454 * disestablish pci interrupts for now (and I doubt we will), 455 * so why bother. 456 */ 457 458 DPRINTF(SPDB_INTR, 459 ("pci_intr_establish: returning handle %p\n", cookie)); 460 return (cookie); 461 } 462 463 464 void 465 pci_intr_disestablish(pc, cookie) 466 pci_chipset_tag_t pc; 467 void *cookie; 468 { 469 470 DPRINTF(SPDB_INTR, ("pci_intr_disestablish: cookie %p\n", cookie)); 471 panic("pci_intr_disestablish: not implemented"); 472 } 473