1 /* $NetBSD: pcib.c,v 1.6 2002/10/02 15:45:18 thorpej Exp $ */ 2 3 /* 4 * Copyright 2002 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Simon Burge for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/kernel.h> 41 #include <sys/device.h> 42 #include <sys/malloc.h> 43 44 #include <machine/bus.h> 45 #include <evbmips/malta/maltareg.h> 46 #include <evbmips/malta/maltavar.h> 47 #include <evbmips/malta/dev/gtreg.h> 48 #include <evbmips/malta/pci/pcibvar.h> 49 50 #include <dev/isa/isareg.h> 51 #include <dev/isa/isavar.h> 52 53 #include <dev/pci/pcireg.h> 54 #include <dev/pci/pcivar.h> 55 #include <dev/pci/pcidevs.h> 56 57 #include <dev/ic/i8259reg.h> 58 59 60 #define ICU_LEN 16 /* number of ISA IRQs */ 61 62 const char *isa_intrnames[ICU_LEN] = { 63 "timer", 64 "keyboard", 65 "reserved", /* by South Bridge (for cascading) */ 66 "com1", 67 "com0", 68 "not used", 69 "floppy", 70 "centronics", 71 "mcclock", 72 "i2c", 73 "pci A,B", /* PCI slots 1..4, ethernet */ 74 "pci C,D", /* PCI slots 1..4, audio, usb */ 75 "mouse", 76 "reserved", 77 "ide primary", 78 "ide secondary", /* and compact flash connector */ 79 }; 80 81 struct pcib_intrhead { 82 LIST_HEAD(, evbmips_intrhand) intr_q; 83 struct evcnt intr_count; 84 int intr_type; 85 }; 86 87 struct pcib_softc { 88 struct device sc_dev; 89 90 bus_space_tag_t sc_iot; 91 bus_space_handle_t sc_ioh_icu1; 92 bus_space_handle_t sc_ioh_icu2; 93 bus_space_handle_t sc_ioh_elcr; 94 95 struct mips_isa_chipset sc_ic; 96 97 struct pcib_intrhead sc_intrtab[ICU_LEN]; 98 99 u_int16_t sc_imask; 100 u_int16_t sc_elcr; 101 102 u_int16_t sc_reserved; 103 104 void *sc_ih; 105 }; 106 107 /* 108 * XXX 109 * There is only one pci-isa bridge, and all external interrupts 110 * are routed through it, so we need to remember the softc when 111 * called from other interrupt handling code. 112 */ 113 static struct pcib_softc *my_sc; 114 struct mips_isa_chipset *pcib_ic; 115 116 static int pcib_match(struct device *, struct cfdata *, void *); 117 static void pcib_attach(struct device *, struct device *, void *); 118 static int pcib_intr(void *v); 119 static void pcib_bridge_callback(struct device *); 120 static int pcib_print(void *, const char *); 121 static void pcib_set_icus(struct pcib_softc *sc); 122 static void pcib_cleanup(void *arg); 123 124 static const struct evcnt * 125 pcib_isa_intr_evcnt(void *, int); 126 static void *pcib_isa_intr_establish(void *, int, int, int, 127 int (*)(void *), void *); 128 static void pcib_isa_intr_disestablish(void *, void *); 129 static void pcib_isa_attach_hook(struct device *, struct device *, 130 struct isabus_attach_args *); 131 static int pcib_isa_intr_alloc(void *, int, int, int *); 132 static const char * 133 pcib_isa_intr_string(void *, int); 134 135 CFATTACH_DECL(pcib, sizeof(struct pcib_softc), 136 pcib_match, pcib_attach, NULL, NULL); 137 138 static int 139 pcib_match(struct device *parent, struct cfdata *match, void *aux) 140 { 141 struct pci_attach_args *pa = aux; 142 143 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE && 144 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_ISA) 145 return (1); 146 147 return (0); 148 } 149 150 static void 151 pcib_attach(struct device *parent, struct device *self, void *aux) 152 { 153 struct pci_attach_args *pa = aux; 154 char devinfo[256]; 155 int i; 156 157 printf("\n"); 158 159 if (my_sc != NULL) 160 panic("pcib_attach: already attached!"); 161 my_sc = (void *)self; 162 163 /* 164 * Just print out a description and defer configuration 165 * until all PCI devices have been attached. 166 */ 167 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo); 168 printf("%s: %s, (rev . 0x%02x)\n", self->dv_xname, devinfo, 169 PCI_REVISION(pa->pa_class)); 170 171 my_sc->sc_iot = pa->pa_iot; 172 173 /* 174 * Map the PIC/ELCR registers. 175 */ 176 if (bus_space_map(my_sc->sc_iot, 0x4d0, 2, 0, &my_sc->sc_ioh_elcr) != 0) 177 printf("%s: unable to map ELCR registers\n", 178 my_sc->sc_dev.dv_xname); 179 if (bus_space_map(my_sc->sc_iot, IO_ICU1, 2, 0, &my_sc->sc_ioh_icu1) != 0) 180 printf("%s: unable to map ICU1 registers\n", 181 my_sc->sc_dev.dv_xname); 182 if (bus_space_map(my_sc->sc_iot, IO_ICU2, 2, 0, &my_sc->sc_ioh_icu2) != 0) 183 printf("%s: unable to map ICU2 registers\n", 184 my_sc->sc_dev.dv_xname); 185 186 /* All interrupts default to "masked off". */ 187 my_sc->sc_imask = 0xffff; 188 189 /* All interrupts default to edge-triggered. */ 190 my_sc->sc_elcr = 0; 191 192 /* 193 * Initialize the 8259s. 194 */ 195 /* reset, program device, 4 bytes */ 196 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_ICW1, 197 ICW1_SELECT | ICW1_IC4); 198 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_ICW2, 199 ICW2_VECTOR(0)/*XXX*/); 200 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_ICW3, 201 ICW3_CASCADE(2)); 202 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_ICW4, 203 ICW4_8086); 204 205 /* mask all interrupts */ 206 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_OCW1, 207 my_sc->sc_imask & 0xff); 208 209 /* enable special mask mode */ 210 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_OCW3, 211 OCW3_SELECT | OCW3_SSMM | OCW3_SMM); 212 213 /* read IRR by default */ 214 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_OCW3, 215 OCW3_SELECT | OCW3_RR); 216 217 /* reset, program device, 4 bytes */ 218 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_ICW1, 219 ICW1_SELECT | ICW1_IC4); 220 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_ICW2, 221 ICW2_VECTOR(0)/*XXX*/); 222 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_ICW3, 223 ICW3_CASCADE(2)); 224 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_ICW4, 225 ICW4_8086); 226 227 /* mask all interrupts */ 228 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_OCW1, 229 my_sc->sc_imask & 0xff); 230 231 /* enable special mask mode */ 232 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_OCW3, 233 OCW3_SELECT | OCW3_SSMM | OCW3_SMM); 234 235 /* read IRR by default */ 236 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_OCW3, 237 OCW3_SELECT | OCW3_RR); 238 239 /* 240 * Default all interrupts to edge-triggered. 241 */ 242 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_elcr, 0, 243 my_sc->sc_elcr & 0xff); 244 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_elcr, 1, 245 (my_sc->sc_elcr >> 8) & 0xff); 246 247 /* 248 * Some ISA interrupts are reserved for devices that 249 * we know are hard-wired to certain IRQs. 250 */ 251 my_sc->sc_reserved = 252 (1U << 0) | /* timer */ 253 (1U << 1) | /* keyboard controller (keyboard) */ 254 (1U << 2) | /* PIC cascade */ 255 (1U << 3) | /* COM 2 */ 256 (1U << 4) | /* COM 1 */ 257 (1U << 6) | /* floppy */ 258 (1U << 7) | /* centronics */ 259 (1U << 8) | /* RTC */ 260 (1U << 9) | /* I2C */ 261 (1U << 12) | /* keyboard controller (mouse) */ 262 (1U << 14) | /* IDE primary */ 263 (1U << 15); /* IDE secondary */ 264 265 /* Set up our ISA chipset. */ 266 my_sc->sc_ic.ic_v = my_sc; 267 my_sc->sc_ic.ic_intr_evcnt = pcib_isa_intr_evcnt; 268 my_sc->sc_ic.ic_intr_establish = pcib_isa_intr_establish; 269 my_sc->sc_ic.ic_intr_disestablish = pcib_isa_intr_disestablish; 270 my_sc->sc_ic.ic_intr_alloc = pcib_isa_intr_alloc; 271 my_sc->sc_ic.ic_intr_string = pcib_isa_intr_string; 272 273 pcib_ic = &my_sc->sc_ic; /* XXX for external use */ 274 275 /* Initialize our interrupt table. */ 276 for (i = 0; i < ICU_LEN; i++) { 277 #if 0 278 char irqstr[8]; /* 4 + 2 + NULL + sanity */ 279 280 sprintf(irqstr, "irq %d", i); 281 evcnt_attach_dynamic(&my_sc->sc_intrtab[i].intr_count, 282 EVCNT_TYPE_INTR, NULL, "pcib", irqstr); 283 #else 284 evcnt_attach_dynamic(&my_sc->sc_intrtab[i].intr_count, 285 EVCNT_TYPE_INTR, NULL, "pcib", isa_intrnames[i]); 286 #endif 287 LIST_INIT(&my_sc->sc_intrtab[i].intr_q); 288 my_sc->sc_intrtab[i].intr_type = IST_NONE; 289 } 290 291 /* Hook up our interrupt handler. */ 292 my_sc->sc_ih = evbmips_intr_establish(MALTA_SOUTHBRIDGE_INTR, pcib_intr, my_sc); 293 if (my_sc->sc_ih == NULL) 294 printf("%s: WARNING: unable to register interrupt handler\n", 295 my_sc->sc_dev.dv_xname); 296 297 298 /* 299 * Disable ISA interrupts before returning to YAMON. 300 */ 301 if (shutdownhook_establish(pcib_cleanup, my_sc) == NULL) 302 panic("pcib_attach: could not establish shutdown hook"); 303 304 config_defer(self, pcib_bridge_callback); 305 } 306 307 static void 308 pcib_bridge_callback(struct device *self) 309 { 310 struct pcib_softc *sc = (void *)self; 311 struct malta_config *mcp = &malta_configuration; 312 struct isabus_attach_args iba; 313 314 /* 315 * Attach the ISA bus behind this bridge. 316 */ 317 memset(&iba, 0, sizeof(iba)); 318 319 iba.iba_busname = "isa"; 320 iba.iba_iot = &mcp->mc_iot; 321 iba.iba_memt = &mcp->mc_memt; 322 iba.iba_dmat = &mcp->mc_isa_dmat; 323 324 iba.iba_ic = &sc->sc_ic; 325 iba.iba_ic->ic_attach_hook = pcib_isa_attach_hook; 326 327 config_found(&sc->sc_dev, &iba, pcib_print); 328 } 329 330 static int 331 pcib_print(void *aux, const char *pnp) 332 { 333 334 /* Only ISAs can attach to pcib's; easy. */ 335 if (pnp) 336 printf("isa at %s", pnp); 337 return (UNCONF); 338 } 339 340 static void 341 pcib_isa_attach_hook(struct device *parent, struct device *self, 342 struct isabus_attach_args *iba) 343 { 344 345 /* Nothing to do. */ 346 } 347 348 static void 349 pcib_set_icus(struct pcib_softc *sc) 350 { 351 352 /* Enable the cascade IRQ (2) if 8-15 is enabled. */ 353 if ((sc->sc_imask & 0xff00) != 0xff00) 354 sc->sc_imask &= ~(1U << 2); 355 else 356 sc->sc_imask |= (1U << 2); 357 358 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW1, 359 sc->sc_imask & 0xff); 360 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW1, 361 (sc->sc_imask >> 8) & 0xff); 362 363 bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 0, 364 sc->sc_elcr & 0xff); 365 bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 1, 366 (sc->sc_elcr >> 8) & 0xff); 367 } 368 369 static int 370 pcib_intr(void *v) 371 { 372 struct pcib_softc *sc = v; 373 struct evbmips_intrhand *ih; 374 int irq; 375 376 for (;;) { 377 #if 1 378 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3, 379 OCW3_SELECT | OCW3_POLL); 380 irq = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3); 381 if ((irq & OCW3_POLL_PENDING) == 0) 382 return (1); 383 384 irq = OCW3_POLL_IRQ(irq); 385 386 if (irq == 2) { 387 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 388 PIC_OCW3, OCW3_SELECT | OCW3_POLL); 389 irq = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu2, 390 PIC_OCW3); 391 if (irq & OCW3_POLL_PENDING) 392 irq = OCW3_POLL_IRQ(irq) + 8; 393 else 394 irq = 2; 395 } 396 #else 397 /* XXX - should be a function call to gt.c? */ 398 irq = GT_REGVAL(GT_PCI0_INTR_ACK) & 0xff; 399 400 /* 401 * From YAMON source code: 402 * 403 * IRQ7 is used to detect spurious interrupts. 404 * The interrupt acknowledge cycle returns IRQ7, if no 405 * interrupts is requested. 406 * We can differentiate between this situation and a 407 * "Normal" IRQ7 by reading the ISR. 408 */ 409 410 if (irq == 7) { 411 int reg; 412 413 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3, 414 OCW3_SELECT | OCW3_RR | OCW3_RIS); 415 reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu1, 416 PIC_OCW3); 417 if (!(reg & (1 << 7))) 418 break; /* spurious interrupt */ 419 } 420 #endif 421 422 sc->sc_intrtab[irq].intr_count.ev_count++; 423 LIST_FOREACH(ih, &sc->sc_intrtab[irq].intr_q, ih_q) 424 (*ih->ih_func)(ih->ih_arg); 425 426 /* Send a specific EOI to the 8259. */ 427 if (irq > 7) { 428 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 429 PIC_OCW2, OCW2_SELECT | OCW3_EOI | OCW3_SL | 430 OCW2_ILS(irq & 7)); 431 irq = 2; 432 } 433 434 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW2, 435 OCW2_SELECT | OCW3_EOI | OCW3_SL | OCW2_ILS(irq)); 436 } 437 } 438 439 const char * 440 pcib_isa_intr_string(void *v, int irq) 441 { 442 static char irqstr[12]; /* 8 + 2 + NULL + sanity */ 443 444 if (irq == 0 || irq >= ICU_LEN || irq == 2) 445 panic("pcib_isa_intr_string: bogus isa irq 0x%x", irq); 446 447 sprintf(irqstr, "isa irq %d", irq); 448 return (irqstr); 449 } 450 451 const struct evcnt * 452 pcib_isa_intr_evcnt(void *v, int irq) 453 { 454 455 if (irq == 0 || irq >= ICU_LEN || irq == 2) 456 panic("pcib_isa_intr_evcnt: bogus isa irq 0x%x", irq); 457 458 return (&my_sc->sc_intrtab[irq].intr_count); 459 } 460 461 void * 462 pcib_isa_intr_establish(void *v, int irq, int type, int level, 463 int (*func)(void *), void *arg) 464 { 465 struct evbmips_intrhand *ih; 466 int s; 467 468 if (irq >= ICU_LEN || irq == 2 || type == IST_NONE) 469 panic("pcib_isa_intr_establish: bad irq or type"); 470 471 switch (my_sc->sc_intrtab[irq].intr_type) { 472 case IST_NONE: 473 my_sc->sc_intrtab[irq].intr_type = type; 474 break; 475 476 case IST_EDGE: 477 case IST_LEVEL: 478 if (type == my_sc->sc_intrtab[irq].intr_type) 479 break; 480 /* FALLTHROUGH */ 481 case IST_PULSE: 482 /* 483 * We can't share interrupts in this case. 484 */ 485 return (NULL); 486 } 487 488 ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT); 489 if (ih == NULL) 490 return (NULL); 491 492 ih->ih_func = func; 493 ih->ih_arg = arg; 494 ih->ih_irq = irq; 495 496 s = splhigh(); 497 498 /* Insert the handler into the table. */ 499 LIST_INSERT_HEAD(&my_sc->sc_intrtab[irq].intr_q, ih, ih_q); 500 my_sc->sc_intrtab[irq].intr_type = type; 501 502 /* Enable it, set trigger mode. */ 503 my_sc->sc_imask &= ~(1 << irq); 504 if (my_sc->sc_intrtab[irq].intr_type == IST_LEVEL) 505 my_sc->sc_elcr |= (1 << irq); 506 else 507 my_sc->sc_elcr &= ~(1 << irq); 508 509 pcib_set_icus(my_sc); 510 511 splx(s); 512 513 return (ih); 514 } 515 516 void 517 pcib_isa_intr_disestablish(void *v, void *arg) 518 { 519 struct evbmips_intrhand *ih = arg; 520 int s; 521 522 s = splhigh(); 523 524 LIST_REMOVE(ih, ih_q); 525 526 /* If there are no more handlers on this IRQ, disable it. */ 527 if (LIST_FIRST(&my_sc->sc_intrtab[ih->ih_irq].intr_q) == NULL) { 528 my_sc->sc_imask |= (1 << ih->ih_irq); 529 pcib_set_icus(my_sc); 530 } 531 532 splx(s); 533 534 free(ih, M_DEVBUF); 535 } 536 537 static int 538 pcib_isa_intr_alloc(void *v, int mask, int type, int *irq) 539 { 540 int i, tmp, bestirq, count; 541 struct evbmips_intrhand *ih; 542 543 if (type == IST_NONE) 544 panic("pcib_intr_alloc: bogus type"); 545 546 bestirq = -1; 547 count = -1; 548 549 mask &= ~my_sc->sc_reserved; 550 551 for (i = 0; i < ICU_LEN; i++) { 552 if ((mask & (1 << i)) == 0) 553 continue; 554 555 switch (my_sc->sc_intrtab[i].intr_type) { 556 case IST_NONE: 557 /* 558 * If nothing's using the IRQ, just return it. 559 */ 560 *irq = i; 561 return (0); 562 563 case IST_EDGE: 564 case IST_LEVEL: 565 if (type != my_sc->sc_intrtab[i].intr_type) 566 continue; 567 /* 568 * If the IRQ is sharable, count the number of 569 * other handlers, and if it's smaller than the 570 * last IRQ like this, remember it. 571 */ 572 tmp = 0; 573 for (ih = LIST_FIRST(&my_sc->sc_intrtab[i].intr_q); 574 ih != NULL; ih = LIST_NEXT(ih, ih_q)) 575 tmp++; 576 if (bestirq == -1 || count > tmp) { 577 bestirq = i; 578 count = tmp; 579 } 580 break; 581 582 case IST_PULSE: 583 /* This just isn't sharable. */ 584 continue; 585 } 586 } 587 588 if (bestirq == -1) 589 return (1); 590 591 *irq = bestirq; 592 return (0); 593 } 594 595 static void 596 pcib_cleanup(void *arg) 597 { 598 599 my_sc->sc_imask = 0xffff; 600 pcib_set_icus(my_sc); 601 } 602