ar724x_pci.c revision 265999
1/*- 2 * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org> 3 * Copyright (c) 2011, Luiz Otavio O Souza. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice unmodified, this list of conditions, and the following 11 * disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD: stable/10/sys/mips/atheros/ar724x_pci.c 265999 2014-05-14 01:35:43Z ian $"); 31 32#include "opt_ar71xx.h" 33 34#include <sys/param.h> 35#include <sys/systm.h> 36 37#include <sys/bus.h> 38#include <sys/interrupt.h> 39#include <sys/malloc.h> 40#include <sys/kernel.h> 41#include <sys/module.h> 42#include <sys/rman.h> 43 44#include <vm/vm.h> 45#include <vm/pmap.h> 46#include <vm/vm_extern.h> 47 48#include <machine/bus.h> 49#include <machine/cpu.h> 50#include <machine/intr_machdep.h> 51#include <machine/pmap.h> 52 53#include <dev/pci/pcivar.h> 54#include <dev/pci/pcireg.h> 55 56#include <dev/pci/pcib_private.h> 57#include "pcib_if.h" 58 59#include <mips/atheros/ar71xxreg.h> 60#include <mips/atheros/ar724xreg.h> 61#include <mips/atheros/ar71xx_setup.h> 62#include <mips/atheros/ar71xx_pci_bus_space.h> 63 64#include <mips/atheros/ar71xx_cpudef.h> 65 66#ifdef AR71XX_ATH_EEPROM 67#include <mips/atheros/ar71xx_fixup.h> 68#endif /* AR71XX_ATH_EEPROM */ 69 70#undef AR724X_PCI_DEBUG 71#ifdef AR724X_PCI_DEBUG 72#define dprintf printf 73#else 74#define dprintf(x, arg...) 75#endif 76 77struct ar71xx_pci_softc { 78 device_t sc_dev; 79 80 int sc_busno; 81 struct rman sc_mem_rman; 82 struct rman sc_irq_rman; 83 84 struct intr_event *sc_eventstab[AR71XX_PCI_NIRQS]; 85 mips_intrcnt_t sc_intr_counter[AR71XX_PCI_NIRQS]; 86 struct resource *sc_irq; 87 void *sc_ih; 88}; 89 90static int ar724x_pci_setup_intr(device_t, device_t, struct resource *, int, 91 driver_filter_t *, driver_intr_t *, void *, void **); 92static int ar724x_pci_teardown_intr(device_t, device_t, struct resource *, 93 void *); 94static int ar724x_pci_intr(void *); 95 96static void 97ar724x_pci_write(uint32_t reg, uint32_t offset, uint32_t data, int bytes) 98{ 99 uint32_t val, mask, shift; 100 101 /* Register access is 32-bit aligned */ 102 shift = (offset & 3) * 8; 103 if (bytes % 4) 104 mask = (1 << (bytes * 8)) - 1; 105 else 106 mask = 0xffffffff; 107 108 val = ATH_READ_REG(reg + (offset & ~3)); 109 val &= ~(mask << shift); 110 val |= ((data & mask) << shift); 111 ATH_WRITE_REG(reg + (offset & ~3), val); 112 113 dprintf("%s: %#x/%#x addr=%#x, data=%#x(%#x), bytes=%d\n", __func__, 114 reg, reg + (offset & ~3), offset, data, val, bytes); 115} 116 117static uint32_t 118ar724x_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func, 119 u_int reg, int bytes) 120{ 121 uint32_t data, shift, mask; 122 123 /* Register access is 32-bit aligned */ 124 shift = (reg & 3) * 8; 125 if (shift) 126 mask = (1 << shift) - 1; 127 else 128 mask = 0xffffffff; 129 130 dprintf("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__, bus, slot, 131 func, reg, bytes); 132 133 if ((bus == 0) && (slot == 0) && (func == 0)) 134 data = ATH_READ_REG(AR724X_PCI_CFG_BASE + (reg & ~3)); 135 else 136 data = -1; 137 138 /* Get request bytes from 32-bit word */ 139 data = (data >> shift) & mask; 140 141 dprintf("%s: read 0x%x\n", __func__, data); 142 143 return (data); 144} 145 146static void 147ar724x_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func, 148 u_int reg, uint32_t data, int bytes) 149{ 150 151 dprintf("%s: tag (%x, %x, %x) reg %d(%d): %x\n", __func__, bus, slot, 152 func, reg, bytes, data); 153 154 if ((bus != 0) || (slot != 0) || (func != 0)) 155 return; 156 157 /* 158 * WAR for BAR issue on AR7240 - We are unable to access the PCI device 159 * space if we set the BAR with proper base address. 160 */ 161 if (reg == PCIR_BAR(0) && bytes == 4 && ar71xx_soc == AR71XX_SOC_AR7240) 162 ar724x_pci_write(AR724X_PCI_CFG_BASE, reg, 0xffff, bytes); 163 else 164 ar724x_pci_write(AR724X_PCI_CFG_BASE, reg, data, bytes); 165} 166 167static void 168ar724x_pci_mask_irq(void *source) 169{ 170 uint32_t reg; 171 unsigned int irq = (unsigned int)source; 172 173 /* XXX - Only one interrupt ? Only one device ? */ 174 if (irq != AR71XX_PCI_IRQ_START) 175 return; 176 177 /* Update the interrupt mask reg */ 178 reg = ATH_READ_REG(AR724X_PCI_INTR_MASK); 179 ATH_WRITE_REG(AR724X_PCI_INTR_MASK, 180 reg & ~AR724X_PCI_INTR_DEV0); 181 182 /* Clear any pending interrupt */ 183 reg = ATH_READ_REG(AR724X_PCI_INTR_STATUS); 184 ATH_WRITE_REG(AR724X_PCI_INTR_STATUS, 185 reg | AR724X_PCI_INTR_DEV0); 186} 187 188static void 189ar724x_pci_unmask_irq(void *source) 190{ 191 uint32_t reg; 192 unsigned int irq = (unsigned int)source; 193 194 /* XXX */ 195 if (irq != AR71XX_PCI_IRQ_START) 196 return; 197 198 /* Update the interrupt mask reg */ 199 reg = ATH_READ_REG(AR724X_PCI_INTR_MASK); 200 ATH_WRITE_REG(AR724X_PCI_INTR_MASK, 201 reg | AR724X_PCI_INTR_DEV0); 202} 203 204static int 205ar724x_pci_setup(device_t dev) 206{ 207 uint32_t reg; 208 209 /* setup COMMAND register */ 210 reg = PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN | PCIM_CMD_SERRESPEN | 211 PCIM_CMD_BACKTOBACK | PCIM_CMD_PERRESPEN | PCIM_CMD_MWRICEN; 212 213 ar724x_pci_write(AR724X_PCI_CRP_BASE, PCIR_COMMAND, reg, 2); 214 ar724x_pci_write(AR724X_PCI_CRP_BASE, 0x20, 0x1ff01000, 4); 215 ar724x_pci_write(AR724X_PCI_CRP_BASE, 0x24, 0x1ff01000, 4); 216 217 reg = ATH_READ_REG(AR724X_PCI_RESET); 218 if (reg != 0x7) { 219 DELAY(100000); 220 ATH_WRITE_REG(AR724X_PCI_RESET, 0); 221 DELAY(100); 222 ATH_WRITE_REG(AR724X_PCI_RESET, 4); 223 DELAY(100000); 224 } 225 226 if (ar71xx_soc == AR71XX_SOC_AR7240) 227 reg = AR724X_PCI_APP_LTSSM_ENABLE; 228 else 229 reg = 0x1ffc1; 230 ATH_WRITE_REG(AR724X_PCI_APP, reg); 231 /* Flush write */ 232 (void) ATH_READ_REG(AR724X_PCI_APP); 233 234 DELAY(1000); 235 236 reg = ATH_READ_REG(AR724X_PCI_RESET); 237 if ((reg & AR724X_PCI_RESET_LINK_UP) == 0) { 238 device_printf(dev, "no PCIe controller found\n"); 239 return (ENXIO); 240 } 241 242 if (ar71xx_soc == AR71XX_SOC_AR7241 || 243 ar71xx_soc == AR71XX_SOC_AR7242) { 244 reg = ATH_READ_REG(AR724X_PCI_APP); 245 reg |= (1 << 16); 246 ATH_WRITE_REG(AR724X_PCI_APP, reg); 247 } 248 249 return (0); 250} 251 252#ifdef AR71XX_ATH_EEPROM 253#define AR5416_EEPROM_MAGIC 0xa55a 254 255/* 256 * XXX - This should not be here ! And this looks like Atheros (if_ath) only. 257 */ 258static void 259ar724x_pci_fixup(device_t dev, long flash_addr, int len) 260{ 261 uint32_t bar0, reg, val; 262 uint16_t *cal_data = (uint16_t *) MIPS_PHYS_TO_KSEG1(flash_addr); 263 264 if (cal_data[0] != AR5416_EEPROM_MAGIC) { 265 device_printf(dev, "%s: Invalid calibration data from 0x%x\n", 266 __func__, (uintptr_t) flash_addr); 267 return; 268 } 269 270 /* Save bar(0) address - just to flush bar(0) (SoC WAR) ? */ 271 bar0 = ar724x_pci_read_config(dev, 0, 0, 0, PCIR_BAR(0), 4); 272 273 /* Write temporary BAR0 to map the NIC into a fixed location */ 274 ar724x_pci_write_config(dev, 0, 0, 0, PCIR_BAR(0), 275 AR71XX_PCI_MEM_BASE, 4); 276 277 val = ar724x_pci_read_config(dev, 0, 0, 0, PCIR_COMMAND, 2); 278 val |= (PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN); 279 ar724x_pci_write_config(dev, 0, 0, 0, PCIR_COMMAND, val, 2); 280 281 /* set pointer to first reg address */ 282 cal_data += 3; 283 while (*cal_data != 0xffff) { 284 reg = *cal_data++; 285 val = *cal_data++; 286 val |= (*cal_data++) << 16; 287 288 if (bootverbose) 289 printf(" 0x%08x=0x%04x\n", reg, val); 290 291 /* Write eeprom fixup data to device memory */ 292 ATH_WRITE_REG(AR71XX_PCI_MEM_BASE + reg, val); 293 DELAY(100); 294 } 295 296 val = ar724x_pci_read_config(dev, 0, 0, 0, PCIR_COMMAND, 2); 297 val &= ~(PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN); 298 ar724x_pci_write_config(dev, 0, 0, 0, PCIR_COMMAND, val, 2); 299 300 /* Write the saved bar(0) address */ 301 ar724x_pci_write_config(dev, 0, 0, 0, PCIR_BAR(0), bar0, 4); 302} 303#undef AR5416_EEPROM_MAGIC 304 305/* 306 * XXX This is (mostly) duplicated with ar71xx_pci.c. 307 * It should at some point be fixed. 308 */ 309static void 310ar724x_pci_slot_fixup(device_t dev) 311{ 312 long int flash_addr; 313 char buf[64]; 314 int size; 315 316 /* 317 * Check whether the given slot has a hint to poke. 318 */ 319 if (bootverbose) 320 device_printf(dev, "%s: checking dev %s, %d/%d/%d\n", 321 __func__, device_get_nameunit(dev), 0, 0, 0); 322 323 snprintf(buf, sizeof(buf), "bus.%d.%d.%d.ath_fixup_addr", 324 0, 0, 0); 325 326 if (resource_long_value(device_get_name(dev), device_get_unit(dev), 327 buf, &flash_addr) == 0) { 328 snprintf(buf, sizeof(buf), "bus.%d.%d.%d.ath_fixup_size", 329 0, 0, 0); 330 if (resource_int_value(device_get_name(dev), 331 device_get_unit(dev), buf, &size) != 0) { 332 device_printf(dev, 333 "%s: missing hint '%s', aborting EEPROM\n", 334 __func__, buf); 335 return; 336 } 337 338 339 device_printf(dev, "found EEPROM at 0x%lx on %d.%d.%d\n", 340 flash_addr, 0, 0, 0); 341 ar724x_pci_fixup(dev, flash_addr, size); 342 ar71xx_pci_slot_create_eeprom_firmware(dev, 0, 0, 0, 343 flash_addr, size); 344 } 345} 346#endif /* AR71XX_ATH_EEPROM */ 347 348static int 349ar724x_pci_probe(device_t dev) 350{ 351 352 return (BUS_PROBE_NOWILDCARD); 353} 354 355static int 356ar724x_pci_attach(device_t dev) 357{ 358 struct ar71xx_pci_softc *sc = device_get_softc(dev); 359 int busno = 0; 360 int rid = 0; 361 362 sc->sc_mem_rman.rm_type = RMAN_ARRAY; 363 sc->sc_mem_rman.rm_descr = "ar724x PCI memory window"; 364 if (rman_init(&sc->sc_mem_rman) != 0 || 365 rman_manage_region(&sc->sc_mem_rman, AR71XX_PCI_MEM_BASE, 366 AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE - 1) != 0) { 367 panic("ar724x_pci_attach: failed to set up I/O rman"); 368 } 369 370 sc->sc_irq_rman.rm_type = RMAN_ARRAY; 371 sc->sc_irq_rman.rm_descr = "ar724x PCI IRQs"; 372 if (rman_init(&sc->sc_irq_rman) != 0 || 373 rman_manage_region(&sc->sc_irq_rman, AR71XX_PCI_IRQ_START, 374 AR71XX_PCI_IRQ_END) != 0) 375 panic("ar724x_pci_attach: failed to set up IRQ rman"); 376 377 /* Disable interrupts */ 378 ATH_WRITE_REG(AR724X_PCI_INTR_STATUS, 0); 379 ATH_WRITE_REG(AR724X_PCI_INTR_MASK, 0); 380 381 /* Hook up our interrupt handler. */ 382 if ((sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 383 RF_SHAREABLE | RF_ACTIVE)) == NULL) { 384 device_printf(dev, "unable to allocate IRQ resource\n"); 385 return (ENXIO); 386 } 387 388 if ((bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC, 389 ar724x_pci_intr, NULL, sc, &sc->sc_ih))) { 390 device_printf(dev, 391 "WARNING: unable to register interrupt handler\n"); 392 return (ENXIO); 393 } 394 395 /* Reset PCIe core and PCIe PHY */ 396 ar71xx_device_stop(AR724X_RESET_PCIE); 397 ar71xx_device_stop(AR724X_RESET_PCIE_PHY); 398 ar71xx_device_stop(AR724X_RESET_PCIE_PHY_SERIAL); 399 DELAY(100); 400 401 ar71xx_device_start(AR724X_RESET_PCIE_PHY_SERIAL); 402 DELAY(100); 403 ar71xx_device_start(AR724X_RESET_PCIE_PHY); 404 ar71xx_device_start(AR724X_RESET_PCIE); 405 406 if (ar724x_pci_setup(dev)) 407 return (ENXIO); 408 409#ifdef AR71XX_ATH_EEPROM 410 ar724x_pci_slot_fixup(dev); 411#endif /* AR71XX_ATH_EEPROM */ 412 413 /* Fixup internal PCI bridge */ 414 ar724x_pci_write_config(dev, 0, 0, 0, PCIR_COMMAND, 415 PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN 416 | PCIM_CMD_SERRESPEN | PCIM_CMD_BACKTOBACK 417 | PCIM_CMD_PERRESPEN | PCIM_CMD_MWRICEN, 2); 418 419 device_add_child(dev, "pci", busno); 420 return (bus_generic_attach(dev)); 421} 422 423static int 424ar724x_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 425{ 426 struct ar71xx_pci_softc *sc = device_get_softc(dev); 427 428 switch (which) { 429 case PCIB_IVAR_DOMAIN: 430 *result = 0; 431 return (0); 432 case PCIB_IVAR_BUS: 433 *result = sc->sc_busno; 434 return (0); 435 } 436 437 return (ENOENT); 438} 439 440static int 441ar724x_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t result) 442{ 443 struct ar71xx_pci_softc * sc = device_get_softc(dev); 444 445 switch (which) { 446 case PCIB_IVAR_BUS: 447 sc->sc_busno = result; 448 return (0); 449 } 450 451 return (ENOENT); 452} 453 454static struct resource * 455ar724x_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, 456 u_long start, u_long end, u_long count, u_int flags) 457{ 458 struct ar71xx_pci_softc *sc = device_get_softc(bus); 459 struct resource *rv; 460 struct rman *rm; 461 462 switch (type) { 463 case SYS_RES_IRQ: 464 rm = &sc->sc_irq_rman; 465 break; 466 case SYS_RES_MEMORY: 467 rm = &sc->sc_mem_rman; 468 break; 469 default: 470 return (NULL); 471 } 472 473 rv = rman_reserve_resource(rm, start, end, count, flags, child); 474 475 if (rv == NULL) 476 return (NULL); 477 478 rman_set_rid(rv, *rid); 479 480 if (flags & RF_ACTIVE) { 481 if (bus_activate_resource(child, type, *rid, rv)) { 482 rman_release_resource(rv); 483 return (NULL); 484 } 485 } 486 487 488 return (rv); 489} 490 491static int 492ar724x_pci_activate_resource(device_t bus, device_t child, int type, int rid, 493 struct resource *r) 494{ 495 int res = (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), 496 child, type, rid, r)); 497 498 if (!res) { 499 switch(type) { 500 case SYS_RES_MEMORY: 501 case SYS_RES_IOPORT: 502 503 rman_set_bustag(r, ar71xx_bus_space_pcimem); 504 break; 505 } 506 } 507 508 return (res); 509} 510 511static int 512ar724x_pci_setup_intr(device_t bus, device_t child, struct resource *ires, 513 int flags, driver_filter_t *filt, driver_intr_t *handler, 514 void *arg, void **cookiep) 515{ 516 struct ar71xx_pci_softc *sc = device_get_softc(bus); 517 struct intr_event *event; 518 int irq, error; 519 520 irq = rman_get_start(ires); 521 if (irq > AR71XX_PCI_IRQ_END) 522 panic("%s: bad irq %d", __func__, irq); 523 524 event = sc->sc_eventstab[irq]; 525 if (event == NULL) { 526 error = intr_event_create(&event, (void *)irq, 0, irq, 527 ar724x_pci_mask_irq, ar724x_pci_unmask_irq, NULL, NULL, 528 "pci intr%d:", irq); 529 530 if (error == 0) { 531 sc->sc_eventstab[irq] = event; 532 sc->sc_intr_counter[irq] = 533 mips_intrcnt_create(event->ie_name); 534 } 535 else 536 return error; 537 } 538 539 intr_event_add_handler(event, device_get_nameunit(child), filt, 540 handler, arg, intr_priority(flags), flags, cookiep); 541 mips_intrcnt_setname(sc->sc_intr_counter[irq], event->ie_fullname); 542 543 ar724x_pci_unmask_irq((void*)irq); 544 545 return (0); 546} 547 548static int 549ar724x_pci_teardown_intr(device_t dev, device_t child, struct resource *ires, 550 void *cookie) 551{ 552 struct ar71xx_pci_softc *sc = device_get_softc(dev); 553 int irq, result; 554 555 irq = rman_get_start(ires); 556 if (irq > AR71XX_PCI_IRQ_END) 557 panic("%s: bad irq %d", __func__, irq); 558 559 if (sc->sc_eventstab[irq] == NULL) 560 panic("Trying to teardown unoccupied IRQ"); 561 562 ar724x_pci_mask_irq((void*)irq); 563 564 result = intr_event_remove_handler(cookie); 565 if (!result) 566 sc->sc_eventstab[irq] = NULL; 567 568 return (result); 569} 570 571static int 572ar724x_pci_intr(void *arg) 573{ 574 struct ar71xx_pci_softc *sc = arg; 575 struct intr_event *event; 576 uint32_t reg, irq, mask; 577 578 ar71xx_device_ddr_flush_ip2(); 579 580 reg = ATH_READ_REG(AR724X_PCI_INTR_STATUS); 581 mask = ATH_READ_REG(AR724X_PCI_INTR_MASK); 582 /* 583 * Handle only unmasked interrupts 584 */ 585 reg &= mask; 586 if (reg & AR724X_PCI_INTR_DEV0) { 587 588 irq = AR71XX_PCI_IRQ_START; 589 event = sc->sc_eventstab[irq]; 590 if (!event || TAILQ_EMPTY(&event->ie_handlers)) { 591 printf("Stray IRQ %d\n", irq); 592 return (FILTER_STRAY); 593 } 594 595 /* TODO: frame instead of NULL? */ 596 intr_event_handle(event, NULL); 597 mips_intrcnt_inc(sc->sc_intr_counter[irq]); 598 } 599 600 return (FILTER_HANDLED); 601} 602 603static int 604ar724x_pci_maxslots(device_t dev) 605{ 606 607 return (PCI_SLOTMAX); 608} 609 610static int 611ar724x_pci_route_interrupt(device_t pcib, device_t device, int pin) 612{ 613 614 return (pci_get_slot(device)); 615} 616 617static device_method_t ar724x_pci_methods[] = { 618 /* Device interface */ 619 DEVMETHOD(device_probe, ar724x_pci_probe), 620 DEVMETHOD(device_attach, ar724x_pci_attach), 621 DEVMETHOD(device_shutdown, bus_generic_shutdown), 622 DEVMETHOD(device_suspend, bus_generic_suspend), 623 DEVMETHOD(device_resume, bus_generic_resume), 624 625 /* Bus interface */ 626 DEVMETHOD(bus_read_ivar, ar724x_pci_read_ivar), 627 DEVMETHOD(bus_write_ivar, ar724x_pci_write_ivar), 628 DEVMETHOD(bus_alloc_resource, ar724x_pci_alloc_resource), 629 DEVMETHOD(bus_release_resource, bus_generic_release_resource), 630 DEVMETHOD(bus_activate_resource, ar724x_pci_activate_resource), 631 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 632 DEVMETHOD(bus_setup_intr, ar724x_pci_setup_intr), 633 DEVMETHOD(bus_teardown_intr, ar724x_pci_teardown_intr), 634 635 /* pcib interface */ 636 DEVMETHOD(pcib_maxslots, ar724x_pci_maxslots), 637 DEVMETHOD(pcib_read_config, ar724x_pci_read_config), 638 DEVMETHOD(pcib_write_config, ar724x_pci_write_config), 639 DEVMETHOD(pcib_route_interrupt, ar724x_pci_route_interrupt), 640 641 DEVMETHOD_END 642}; 643 644static driver_t ar724x_pci_driver = { 645 "pcib", 646 ar724x_pci_methods, 647 sizeof(struct ar71xx_pci_softc), 648}; 649 650static devclass_t ar724x_pci_devclass; 651 652DRIVER_MODULE(ar724x_pci, nexus, ar724x_pci_driver, ar724x_pci_devclass, 0, 0); 653