1 /* $NetBSD: pcib.c,v 1.13 2009/08/19 15:13:56 dyoung 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/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: pcib.c,v 1.13 2009/08/19 15:13:56 dyoung Exp $"); 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/kernel.h> 44 #include <sys/device.h> 45 #include <sys/malloc.h> 46 47 #include <machine/bus.h> 48 #include <evbmips/malta/maltareg.h> 49 #include <evbmips/malta/maltavar.h> 50 #include <evbmips/malta/dev/gtreg.h> 51 #include <evbmips/malta/pci/pcibvar.h> 52 53 #include <dev/isa/isareg.h> 54 #include <dev/isa/isavar.h> 55 56 #include <dev/pci/pcireg.h> 57 #include <dev/pci/pcivar.h> 58 #include <dev/pci/pcidevs.h> 59 60 #include <dev/ic/i8259reg.h> 61 62 63 #define ICU_LEN 16 /* number of ISA IRQs */ 64 65 const char *isa_intrnames[ICU_LEN] = { 66 "timer", 67 "keyboard", 68 "reserved", /* by South Bridge (for cascading) */ 69 "com1", 70 "com0", 71 "not used", 72 "floppy", 73 "centronics", 74 "mcclock", 75 "i2c", 76 "pci A,B", /* PCI slots 1..4, ethernet */ 77 "pci C,D", /* PCI slots 1..4, audio, usb */ 78 "mouse", 79 "reserved", 80 "ide primary", 81 "ide secondary", /* and compact flash connector */ 82 }; 83 84 struct pcib_intrhead { 85 LIST_HEAD(, evbmips_intrhand) intr_q; 86 struct evcnt intr_count; 87 int intr_type; 88 }; 89 90 struct pcib_softc { 91 struct device sc_dev; 92 93 bus_space_tag_t sc_iot; 94 bus_space_handle_t sc_ioh_icu1; 95 bus_space_handle_t sc_ioh_icu2; 96 bus_space_handle_t sc_ioh_elcr; 97 98 struct mips_isa_chipset sc_ic; 99 100 struct pcib_intrhead sc_intrtab[ICU_LEN]; 101 102 u_int16_t sc_imask; 103 u_int16_t sc_elcr; 104 105 u_int16_t sc_reserved; 106 107 void *sc_ih; 108 }; 109 110 /* 111 * XXX 112 * There is only one pci-isa bridge, and all external interrupts 113 * are routed through it, so we need to remember the softc when 114 * called from other interrupt handling code. 115 */ 116 static struct pcib_softc *my_sc; 117 struct mips_isa_chipset *pcib_ic; 118 119 static int pcib_match(struct device *, struct cfdata *, void *); 120 static void pcib_attach(struct device *, struct device *, void *); 121 static int pcib_intr(void *v); 122 static void pcib_bridge_callback(struct device *); 123 static void pcib_set_icus(struct pcib_softc *sc); 124 static void pcib_cleanup(void *arg); 125 126 static const struct evcnt * 127 pcib_isa_intr_evcnt(void *, int); 128 static void *pcib_isa_intr_establish(void *, int, int, int, 129 int (*)(void *), void *); 130 static void pcib_isa_intr_disestablish(void *, void *); 131 static void pcib_isa_attach_hook(struct device *, struct device *, 132 struct isabus_attach_args *); 133 static void pcib_isa_detach_hook(isa_chipset_tag_t, device_t); 134 static int pcib_isa_intr_alloc(void *, int, int, int *); 135 static const char * 136 pcib_isa_intr_string(void *, int); 137 138 CFATTACH_DECL(pcib, sizeof(struct pcib_softc), 139 pcib_match, pcib_attach, NULL, NULL); 140 141 static int 142 pcib_match(struct device *parent, struct cfdata *match, void *aux) 143 { 144 struct pci_attach_args *pa = aux; 145 146 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE && 147 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_ISA) 148 return (1); 149 150 return (0); 151 } 152 153 static void 154 pcib_attach(struct device *parent, struct device *self, void *aux) 155 { 156 struct pci_attach_args *pa = aux; 157 char devinfo[256]; 158 int i; 159 160 printf("\n"); 161 162 if (my_sc != NULL) 163 panic("pcib_attach: already attached!"); 164 my_sc = (void *)self; 165 166 /* 167 * Just print out a description and defer configuration 168 * until all PCI devices have been attached. 169 */ 170 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); 171 printf("%s: %s, (rev . 0x%02x)\n", self->dv_xname, devinfo, 172 PCI_REVISION(pa->pa_class)); 173 174 my_sc->sc_iot = pa->pa_iot; 175 176 /* 177 * Map the PIC/ELCR registers. 178 */ 179 if (bus_space_map(my_sc->sc_iot, 0x4d0, 2, 0, &my_sc->sc_ioh_elcr) != 0) 180 printf("%s: unable to map ELCR registers\n", 181 my_sc->sc_dev.dv_xname); 182 if (bus_space_map(my_sc->sc_iot, IO_ICU1, 2, 0, &my_sc->sc_ioh_icu1) != 0) 183 printf("%s: unable to map ICU1 registers\n", 184 my_sc->sc_dev.dv_xname); 185 if (bus_space_map(my_sc->sc_iot, IO_ICU2, 2, 0, &my_sc->sc_ioh_icu2) != 0) 186 printf("%s: unable to map ICU2 registers\n", 187 my_sc->sc_dev.dv_xname); 188 189 /* All interrupts default to "masked off". */ 190 my_sc->sc_imask = 0xffff; 191 192 /* All interrupts default to edge-triggered. */ 193 my_sc->sc_elcr = 0; 194 195 /* 196 * Initialize the 8259s. 197 */ 198 /* reset, program device, 4 bytes */ 199 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_ICW1, 200 ICW1_SELECT | ICW1_IC4); 201 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_ICW2, 202 ICW2_VECTOR(0)/*XXX*/); 203 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_ICW3, 204 ICW3_CASCADE(2)); 205 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_ICW4, 206 ICW4_8086); 207 208 /* mask all interrupts */ 209 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_OCW1, 210 my_sc->sc_imask & 0xff); 211 212 /* enable special mask mode */ 213 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_OCW3, 214 OCW3_SELECT | OCW3_SSMM | OCW3_SMM); 215 216 /* read IRR by default */ 217 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_OCW3, 218 OCW3_SELECT | OCW3_RR); 219 220 /* reset, program device, 4 bytes */ 221 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_ICW1, 222 ICW1_SELECT | ICW1_IC4); 223 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_ICW2, 224 ICW2_VECTOR(0)/*XXX*/); 225 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_ICW3, 226 ICW3_CASCADE(2)); 227 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_ICW4, 228 ICW4_8086); 229 230 /* mask all interrupts */ 231 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_OCW1, 232 my_sc->sc_imask & 0xff); 233 234 /* enable special mask mode */ 235 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_OCW3, 236 OCW3_SELECT | OCW3_SSMM | OCW3_SMM); 237 238 /* read IRR by default */ 239 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_OCW3, 240 OCW3_SELECT | OCW3_RR); 241 242 /* 243 * Default all interrupts to edge-triggered. 244 */ 245 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_elcr, 0, 246 my_sc->sc_elcr & 0xff); 247 bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_elcr, 1, 248 (my_sc->sc_elcr >> 8) & 0xff); 249 250 /* 251 * Some ISA interrupts are reserved for devices that 252 * we know are hard-wired to certain IRQs. 253 */ 254 my_sc->sc_reserved = 255 (1U << 0) | /* timer */ 256 (1U << 1) | /* keyboard controller (keyboard) */ 257 (1U << 2) | /* PIC cascade */ 258 (1U << 3) | /* COM 2 */ 259 (1U << 4) | /* COM 1 */ 260 (1U << 6) | /* floppy */ 261 (1U << 7) | /* centronics */ 262 (1U << 8) | /* RTC */ 263 (1U << 9) | /* I2C */ 264 (1U << 12) | /* keyboard controller (mouse) */ 265 (1U << 14) | /* IDE primary */ 266 (1U << 15); /* IDE secondary */ 267 268 /* Set up our ISA chipset. */ 269 my_sc->sc_ic.ic_v = my_sc; 270 my_sc->sc_ic.ic_intr_evcnt = pcib_isa_intr_evcnt; 271 my_sc->sc_ic.ic_intr_establish = pcib_isa_intr_establish; 272 my_sc->sc_ic.ic_intr_disestablish = pcib_isa_intr_disestablish; 273 my_sc->sc_ic.ic_intr_alloc = pcib_isa_intr_alloc; 274 my_sc->sc_ic.ic_intr_string = pcib_isa_intr_string; 275 276 pcib_ic = &my_sc->sc_ic; /* XXX for external use */ 277 278 /* Initialize our interrupt table. */ 279 for (i = 0; i < ICU_LEN; i++) { 280 #if 0 281 char irqstr[8]; /* 4 + 2 + NULL + sanity */ 282 283 sprintf(irqstr, "irq %d", i); 284 evcnt_attach_dynamic(&my_sc->sc_intrtab[i].intr_count, 285 EVCNT_TYPE_INTR, NULL, "pcib", irqstr); 286 #else 287 evcnt_attach_dynamic(&my_sc->sc_intrtab[i].intr_count, 288 EVCNT_TYPE_INTR, NULL, "pcib", isa_intrnames[i]); 289 #endif 290 LIST_INIT(&my_sc->sc_intrtab[i].intr_q); 291 my_sc->sc_intrtab[i].intr_type = IST_NONE; 292 } 293 294 /* Hook up our interrupt handler. */ 295 my_sc->sc_ih = evbmips_intr_establish(MALTA_SOUTHBRIDGE_INTR, pcib_intr, my_sc); 296 if (my_sc->sc_ih == NULL) 297 printf("%s: WARNING: unable to register interrupt handler\n", 298 my_sc->sc_dev.dv_xname); 299 300 301 /* 302 * Disable ISA interrupts before returning to YAMON. 303 */ 304 if (shutdownhook_establish(pcib_cleanup, my_sc) == NULL) 305 panic("pcib_attach: could not establish shutdown hook"); 306 307 config_defer(self, pcib_bridge_callback); 308 } 309 310 static void 311 pcib_bridge_callback(struct device *self) 312 { 313 struct pcib_softc *sc = (void *)self; 314 struct malta_config *mcp = &malta_configuration; 315 struct isabus_attach_args iba; 316 317 /* 318 * Attach the ISA bus behind this bridge. 319 */ 320 memset(&iba, 0, sizeof(iba)); 321 322 iba.iba_iot = &mcp->mc_iot; 323 iba.iba_memt = &mcp->mc_memt; 324 iba.iba_dmat = &mcp->mc_isa_dmat; 325 326 iba.iba_ic = &sc->sc_ic; 327 iba.iba_ic->ic_attach_hook = pcib_isa_attach_hook; 328 iba.iba_ic->ic_detach_hook = pcib_isa_detach_hook; 329 330 config_found_ia(&sc->sc_dev, "isabus", &iba, isabusprint); 331 } 332 333 static void 334 pcib_isa_attach_hook(struct device *parent, struct device *self, 335 struct isabus_attach_args *iba) 336 { 337 338 /* Nothing to do. */ 339 } 340 341 static void 342 pcib_isa_detach_hook(isa_chipset_tag_t ic, device_t self) 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 | OCW2_EOI | OCW2_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 | OCW2_EOI | OCW2_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