ar71xx_pci.c revision 192822
1/*- 2 * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice unmodified, this list of conditions, and the following 10 * disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> 29__FBSDID("$FreeBSD$"); 30 31#include <sys/param.h> 32#include <sys/systm.h> 33 34#include <sys/bus.h> 35#include <sys/interrupt.h> 36#include <sys/malloc.h> 37#include <sys/kernel.h> 38#include <sys/module.h> 39#include <sys/rman.h> 40 41#include <vm/vm.h> 42#include <vm/pmap.h> 43#include <vm/vm_extern.h> 44 45#include <machine/bus.h> 46#include <machine/cpu.h> 47#include <machine/pmap.h> 48 49#include <dev/pci/pcivar.h> 50#include <dev/pci/pcireg.h> 51 52#include <dev/pci/pcib_private.h> 53#include "pcib_if.h" 54 55#include <mips/atheros/ar71xxreg.h> 56#include <mips/atheros/ar71xx_pci_bus_space.h> 57 58#undef AR71XX_PCI_DEBUG 59#ifdef AR71XX_PCI_DEBUG 60#define dprintf printf 61#else 62#define dprintf(x, arg...) 63#endif 64 65struct ar71xx_pci_softc { 66 device_t sc_dev; 67 68 int sc_busno; 69 struct rman sc_mem_rman; 70 struct rman sc_irq_rman; 71 72 struct intr_event *sc_eventstab[AR71XX_PCI_NIRQS]; 73 struct resource *sc_irq; 74 void *sc_ih; 75}; 76 77static int ar71xx_pci_setup_intr(device_t, device_t, struct resource *, int, 78 driver_filter_t *, driver_intr_t *, void *, void **); 79static int ar71xx_pci_teardown_intr(device_t, device_t, struct resource *, 80 void *); 81static int ar71xx_pci_intr(void *); 82 83static void 84ar71xx_pci_mask_irq(void *source) 85{ 86 uint32_t reg; 87 unsigned int irq = (unsigned int)source; 88 89 reg = ATH_READ_REG(AR71XX_PCI_INTR_MASK); 90 ATH_WRITE_REG(AR71XX_PCI_INTR_MASK, reg & ~(1 << irq)); 91 92} 93 94static void 95ar71xx_pci_unmask_irq(void *source) 96{ 97 uint32_t reg; 98 unsigned int irq = (unsigned int)source; 99 100 reg = ATH_READ_REG(AR71XX_PCI_INTR_MASK); 101 ATH_WRITE_REG(AR71XX_PCI_INTR_MASK, reg | (1 << irq)); 102} 103 104/* 105 * get bitmask for bytes of interest: 106 * 0 - we want this byte, 1 - ignore it. e.g: we read 1 byte 107 * from register 7. Bitmask would be: 0111 108 */ 109static uint32_t 110ar71xx_get_bytes_to_read(int reg, int bytes) 111{ 112 uint32_t bytes_to_read = 0; 113 if ((bytes % 4) == 0) 114 bytes_to_read = 0; 115 else if ((bytes % 4) == 1) 116 bytes_to_read = (~(1 << (reg % 4))) & 0xf; 117 else if ((bytes % 4) == 2) 118 bytes_to_read = (~(3 << (reg % 4))) & 0xf; 119 else 120 panic("%s: wrong combination", __func__); 121 122 return (bytes_to_read); 123} 124 125static int 126ar71xx_pci_check_bus_error(void) 127{ 128 uint32_t error, addr, has_errors = 0; 129 error = ATH_READ_REG(AR71XX_PCI_ERROR) & 0x3; 130 dprintf("%s: PCI error = %02x\n", __func__, error); 131 if (error) { 132 addr = ATH_READ_REG(AR71XX_PCI_ERROR_ADDR); 133 134 /* Do not report it yet */ 135#if 0 136 printf("PCI bus error %d at addr 0x%08x\n", error, addr); 137#endif 138 ATH_WRITE_REG(AR71XX_PCI_ERROR, error); 139 has_errors = 1; 140 } 141 142 error = ATH_READ_REG(AR71XX_PCI_AHB_ERROR) & 0x1; 143 dprintf("%s: AHB error = %02x\n", __func__, error); 144 if (error) { 145 addr = ATH_READ_REG(AR71XX_PCI_AHB_ERROR_ADDR); 146 /* Do not report it yet */ 147#if 0 148 printf("AHB bus error %d at addr 0x%08x\n", error, addr); 149#endif 150 ATH_WRITE_REG(AR71XX_PCI_AHB_ERROR, error); 151 has_errors = 1; 152 } 153 154 return (has_errors); 155} 156 157static uint32_t 158ar71xx_pci_make_addr(int bus, int slot, int func, int reg) 159{ 160 if (bus == 0) { 161 return ((1 << slot) | (func << 8) | (reg & ~3)); 162 } else { 163 return ((bus << 16) | (slot << 11) | (func << 8) 164 | (reg & ~3) | 1); 165 } 166} 167 168static int 169ar71xx_pci_conf_setup(int bus, int slot, int func, int reg, int bytes, 170 uint32_t cmd) 171{ 172 uint32_t addr = ar71xx_pci_make_addr(bus, slot, func, (reg & ~3)); 173 cmd |= (ar71xx_get_bytes_to_read(reg, bytes) << 4); 174 175 ATH_WRITE_REG(AR71XX_PCI_CONF_ADDR, addr); 176 ATH_WRITE_REG(AR71XX_PCI_CONF_CMD, cmd); 177 178 dprintf("%s: tag (%x, %x, %x) %d/%d addr=%08x, cmd=%08x\n", __func__, 179 bus, slot, func, reg, bytes, addr, cmd); 180 181 return ar71xx_pci_check_bus_error(); 182} 183 184static uint32_t 185ar71xx_pci_read_config(device_t dev, int bus, int slot, int func, int reg, 186 int bytes) 187{ 188 uint32_t data; 189 uint32_t cmd, shift, mask; 190 191 /* register access is 32-bit aligned */ 192 shift = (reg & 3) * 8; 193 if (shift) 194 mask = (1 << shift) - 1; 195 else 196 mask = 0xffffffff; 197 198 dprintf("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__, bus, slot, 199 func, reg, bytes); 200 201 if ((bus == 0) && (slot == 0) && (func == 0)) { 202 cmd = PCI_LCONF_CMD_READ | (reg & ~3); 203 ATH_WRITE_REG(AR71XX_PCI_LCONF_CMD, cmd); 204 data = ATH_READ_REG(AR71XX_PCI_LCONF_READ_DATA); 205 } else { 206 if (ar71xx_pci_conf_setup(bus, slot, func, reg, bytes, 207 PCI_CONF_CMD_READ) == 0) 208 data = ATH_READ_REG(AR71XX_PCI_CONF_READ_DATA); 209 else 210 data = -1; 211 } 212 213 /* get request bytes from 32-bit word */ 214 data = (data >> shift) & mask; 215 216 dprintf("%s: read 0x%x\n", __func__, data); 217 218 return (data); 219} 220 221static void 222ar71xx_pci_write_config(device_t dev, int bus, int slot, int func, int reg, 223 uint32_t data, int bytes) 224{ 225 uint32_t cmd; 226 227 dprintf("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__, bus, slot, 228 func, reg, bytes); 229 230 data = data << (8*(reg % 4)); 231 232 if ((bus == 0) && (slot == 0) && (func == 0)) { 233 cmd = PCI_LCONF_CMD_WRITE | (reg & ~3); 234 cmd |= ar71xx_get_bytes_to_read(reg, bytes) << 20; 235 ATH_WRITE_REG(AR71XX_PCI_LCONF_CMD, cmd); 236 ATH_WRITE_REG(AR71XX_PCI_LCONF_WRITE_DATA, data); 237 } else { 238 if (ar71xx_pci_conf_setup(bus, slot, func, reg, bytes, 239 PCI_CONF_CMD_WRITE) == 0) 240 ATH_WRITE_REG(AR71XX_PCI_CONF_WRITE_DATA, data); 241 } 242} 243 244static int 245ar71xx_pci_probe(device_t dev) 246{ 247 248 return (0); 249} 250 251static int 252ar71xx_pci_attach(device_t dev) 253{ 254 int busno = 0; 255 int rid = 0; 256 uint32_t reset; 257 struct ar71xx_pci_softc *sc = device_get_softc(dev); 258 259 sc->sc_mem_rman.rm_type = RMAN_ARRAY; 260 sc->sc_mem_rman.rm_descr = "ar71xx PCI memory window"; 261 if (rman_init(&sc->sc_mem_rman) != 0 || 262 rman_manage_region(&sc->sc_mem_rman, AR71XX_PCI_MEM_BASE, 263 AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE - 1) != 0) { 264 panic("ar71xx_pci_attach: failed to set up I/O rman"); 265 } 266 267 sc->sc_irq_rman.rm_type = RMAN_ARRAY; 268 sc->sc_irq_rman.rm_descr = "ar71xx PCI IRQs"; 269 if (rman_init(&sc->sc_irq_rman) != 0 || 270 rman_manage_region(&sc->sc_irq_rman, AR71XX_PCI_IRQ_START, 271 AR71XX_PCI_IRQ_END) != 0) 272 panic("ar71xx_pci_attach: failed to set up IRQ rman"); 273 274 275 ATH_WRITE_REG(AR71XX_PCI_INTR_STATUS, 0); 276 ATH_WRITE_REG(AR71XX_PCI_INTR_MASK, 0); 277 278 /* Hook up our interrupt handler. */ 279 if ((sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 280 RF_SHAREABLE | RF_ACTIVE)) == NULL) { 281 device_printf(dev, "unable to allocate IRQ resource\n"); 282 return ENXIO; 283 } 284 285 if ((bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC, 286 ar71xx_pci_intr, NULL, sc, &sc->sc_ih))) { 287 device_printf(dev, 288 "WARNING: unable to register interrupt handler\n"); 289 return ENXIO; 290 } 291 292 /* reset PCI core and PCI bus */ 293 reset = ATH_READ_REG(AR71XX_RST_RESET); 294 reset |= (RST_RESET_PCI_CORE | RST_RESET_PCI_BUS); 295 ATH_WRITE_REG(AR71XX_RST_RESET, reset); 296 DELAY(1000); 297 298 reset &= ~(RST_RESET_PCI_CORE | RST_RESET_PCI_BUS); 299 ATH_WRITE_REG(AR71XX_RST_RESET, reset); 300 DELAY(1000); 301 302 /* Init PCI windows */ 303 ATH_WRITE_REG(AR71XX_PCI_WINDOW0, PCI_WINDOW0_ADDR); 304 ATH_WRITE_REG(AR71XX_PCI_WINDOW1, PCI_WINDOW1_ADDR); 305 ATH_WRITE_REG(AR71XX_PCI_WINDOW2, PCI_WINDOW2_ADDR); 306 ATH_WRITE_REG(AR71XX_PCI_WINDOW3, PCI_WINDOW3_ADDR); 307 ATH_WRITE_REG(AR71XX_PCI_WINDOW4, PCI_WINDOW4_ADDR); 308 ATH_WRITE_REG(AR71XX_PCI_WINDOW5, PCI_WINDOW5_ADDR); 309 ATH_WRITE_REG(AR71XX_PCI_WINDOW6, PCI_WINDOW6_ADDR); 310 ATH_WRITE_REG(AR71XX_PCI_WINDOW7, PCI_WINDOW7_CONF_ADDR); 311 DELAY(1000); 312 313 ar71xx_pci_check_bus_error(); 314 315 /* Fixup internal PCI bridge */ 316 ar71xx_pci_write_config(dev, 0, 0, 0, PCIR_COMMAND, 317 PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN 318 | PCIM_CMD_SERRESPEN | PCIM_CMD_BACKTOBACK 319 | PCIM_CMD_PERRESPEN | PCIM_CMD_MWRICEN, 2); 320 321 device_add_child(dev, "pci", busno); 322 return (bus_generic_attach(dev)); 323} 324 325static int 326ar71xx_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 327{ 328 struct ar71xx_pci_softc *sc = device_get_softc(dev); 329 330 switch (which) { 331 case PCIB_IVAR_DOMAIN: 332 *result = 0; 333 return (0); 334 case PCIB_IVAR_BUS: 335 *result = sc->sc_busno; 336 return (0); 337 } 338 339 return (ENOENT); 340} 341 342static int 343ar71xx_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t result) 344{ 345 struct ar71xx_pci_softc * sc = device_get_softc(dev); 346 347 switch (which) { 348 case PCIB_IVAR_BUS: 349 sc->sc_busno = result; 350 return (0); 351 } 352 353 return (ENOENT); 354} 355 356static struct resource * 357ar71xx_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, 358 u_long start, u_long end, u_long count, u_int flags) 359{ 360 361 struct ar71xx_pci_softc *sc = device_get_softc(bus); 362 struct resource *rv; 363 struct rman *rm; 364 365 switch (type) { 366 case SYS_RES_IRQ: 367 rm = &sc->sc_irq_rman; 368 break; 369 case SYS_RES_MEMORY: 370 rm = &sc->sc_mem_rman; 371 break; 372 default: 373 return (NULL); 374 } 375 376 rv = rman_reserve_resource(rm, start, end, count, flags, child); 377 378 if (rv == NULL) 379 return (NULL); 380 381 rman_set_rid(rv, *rid); 382 383 if (flags & RF_ACTIVE) { 384 if (bus_activate_resource(child, type, *rid, rv)) { 385 rman_release_resource(rv); 386 return (NULL); 387 } 388 } 389 390 391 return (rv); 392} 393 394 395static int 396ar71xx_pci_activate_resource(device_t bus, device_t child, int type, int rid, 397 struct resource *r) 398{ 399 int res = (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), 400 child, type, rid, r)); 401 402 if (!res) { 403 switch(type) { 404 case SYS_RES_MEMORY: 405 case SYS_RES_IOPORT: 406 rman_set_bustag(r, ar71xx_bus_space_pcimem); 407 break; 408 } 409 } 410 411 return (res); 412} 413 414 415 416static int 417ar71xx_pci_setup_intr(device_t bus, device_t child, struct resource *ires, 418 int flags, driver_filter_t *filt, driver_intr_t *handler, 419 void *arg, void **cookiep) 420{ 421 struct ar71xx_pci_softc *sc = device_get_softc(bus); 422 struct intr_event *event; 423 int irq, error; 424 425 irq = rman_get_start(ires); 426 427 if (irq > AR71XX_PCI_IRQ_END) 428 panic("%s: bad irq %d", __func__, irq); 429 430 event = sc->sc_eventstab[irq]; 431 if (event == NULL) { 432 error = intr_event_create(&event, (void *)irq, 0, irq, 433 ar71xx_pci_mask_irq, ar71xx_pci_unmask_irq, NULL, NULL, 434 "ar71xx_pci intr%d:", irq); 435 436 sc->sc_eventstab[irq] = event; 437 } 438 439 intr_event_add_handler(event, device_get_nameunit(child), filt, 440 handler, arg, intr_priority(flags), flags, cookiep); 441 442 ar71xx_pci_unmask_irq((void*)irq); 443 444 return (0); 445} 446 447static int 448ar71xx_pci_teardown_intr(device_t dev, device_t child, struct resource *ires, 449 void *cookie) 450{ 451 struct ar71xx_pci_softc *sc = device_get_softc(dev); 452 int irq, result; 453 454 irq = rman_get_start(ires); 455 if (irq > AR71XX_PCI_IRQ_END) 456 panic("%s: bad irq %d", __func__, irq); 457 458 if (sc->sc_eventstab[irq] == NULL) 459 panic("Trying to teardown unoccupied IRQ"); 460 461 ar71xx_pci_mask_irq((void*)irq); 462 463 result = intr_event_remove_handler(cookie); 464 if (!result) 465 sc->sc_eventstab[irq] = NULL; 466 467 return (result); 468} 469 470static int 471ar71xx_pci_intr(void *arg) 472{ 473 struct ar71xx_pci_softc *sc = arg; 474 struct intr_event *event; 475 uint32_t reg, irq; 476 477 reg = ATH_READ_REG(AR71XX_PCI_INTR_STATUS); 478 for (irq = AR71XX_PCI_IRQ_START; irq <= AR71XX_PCI_IRQ_END; irq++) { 479 if (reg & (1 << irq)) { 480 event = sc->sc_eventstab[irq]; 481 if (!event || TAILQ_EMPTY(&event->ie_handlers)) { 482 /* Ignore timer interrupts */ 483 if (irq != 0) 484 printf("Stray IRQ %d\n", irq); 485 continue; 486 } 487 488 /* TODO: frame instead of NULL? */ 489 intr_event_handle(event, NULL); 490 } 491 } 492 493 return (FILTER_HANDLED); 494} 495 496static int 497ar71xx_pci_maxslots(device_t dev) 498{ 499 500 return (PCI_SLOTMAX); 501} 502 503static int 504ar71xx_pci_route_interrupt(device_t pcib, device_t device, int pin) 505{ 506 507 return (pin); 508} 509 510static device_method_t ar71xx_pci_methods[] = { 511 /* Device interface */ 512 DEVMETHOD(device_probe, ar71xx_pci_probe), 513 DEVMETHOD(device_attach, ar71xx_pci_attach), 514 DEVMETHOD(device_shutdown, bus_generic_shutdown), 515 DEVMETHOD(device_suspend, bus_generic_suspend), 516 DEVMETHOD(device_resume, bus_generic_resume), 517 518 /* Bus interface */ 519 DEVMETHOD(bus_print_child, bus_generic_print_child), 520 DEVMETHOD(bus_read_ivar, ar71xx_pci_read_ivar), 521 DEVMETHOD(bus_write_ivar, ar71xx_pci_write_ivar), 522 DEVMETHOD(bus_alloc_resource, ar71xx_pci_alloc_resource), 523 DEVMETHOD(bus_release_resource, bus_generic_release_resource), 524 DEVMETHOD(bus_activate_resource, ar71xx_pci_activate_resource), 525 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 526 DEVMETHOD(bus_setup_intr, ar71xx_pci_setup_intr), 527 DEVMETHOD(bus_teardown_intr, ar71xx_pci_teardown_intr), 528 529 /* pcib interface */ 530 DEVMETHOD(pcib_maxslots, ar71xx_pci_maxslots), 531 DEVMETHOD(pcib_read_config, ar71xx_pci_read_config), 532 DEVMETHOD(pcib_write_config, ar71xx_pci_write_config), 533 DEVMETHOD(pcib_route_interrupt, ar71xx_pci_route_interrupt), 534 535 {0, 0} 536}; 537 538static driver_t ar71xx_pci_driver = { 539 "pcib", 540 ar71xx_pci_methods, 541 sizeof(struct ar71xx_pci_softc), 542}; 543 544static devclass_t ar71xx_pci_devclass; 545 546DRIVER_MODULE(ar71xx_pci, nexus, ar71xx_pci_driver, ar71xx_pci_devclass, 0, 0); 547