mv_pci.c revision 185098
1/*- 2 * Copyright (C) 2008 MARVELL INTERNATIONAL LTD. 3 * All rights reserved. 4 * 5 * Developed by Semihalf. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following 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 * 3. Neither the name of MARVELL nor the names of contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, 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 * Marvell integrated PCI/PCI-Express controller driver. 34 */ 35 36#include <sys/cdefs.h> 37__FBSDID("$FreeBSD: head/sys/arm/mv/mv_pci.c 185098 2008-11-19 17:07:01Z raj $"); 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/kernel.h> 42#include <sys/lock.h> 43#include <sys/malloc.h> 44#include <sys/module.h> 45#include <sys/mutex.h> 46#include <sys/queue.h> 47#include <sys/bus.h> 48#include <sys/rman.h> 49#include <sys/endian.h> 50 51#include <vm/vm.h> 52#include <vm/pmap.h> 53 54#include <dev/pci/pcivar.h> 55#include <dev/pci/pcireg.h> 56#include <dev/pci/pcib_private.h> 57 58#include "pcib_if.h" 59 60#include <machine/resource.h> 61#include <machine/bus.h> 62 63#include <arm/mv/mvreg.h> 64#include <arm/mv/mvvar.h> 65 66#define PCI_CFG_ENA (1 << 31) 67#define PCI_CFG_BUS(bus) (((bus) & 0xff) << 16) 68#define PCI_CFG_DEV(dev) (((dev) & 0x1f) << 11) 69#define PCI_CFG_FUN(fun) (((fun) & 0x7) << 8) 70#define PCI_CFG_PCIE_REG(reg) ((reg) & 0xfc) 71 72#define PCI_REG_CFG_ADDR 0x0C78 73#define PCI_REG_CFG_DATA 0x0C7C 74#define PCI_REG_P2P_CONF 0x1D14 75 76#define PCIE_REG_CFG_ADDR 0x18F8 77#define PCIE_REG_CFG_DATA 0x18FC 78#define PCIE_REG_CONTROL 0x1A00 79#define PCIE_CTRL_LINK1X 0x00000001 80#define PCIE_REG_STATUS 0x1A04 81#define PCIE_REG_IRQ_MASK 0x1910 82 83#define STATUS_BUS_OFFS 8 84#define STATUS_BUS_MASK (0xFF << STATUS_BUS_OFFS) 85#define STATUS_DEV_OFFS 16 86#define STATUS_DEV_MASK (0x1F << STATUS_DEV_OFFS) 87 88#define P2P_CONF_BUS_OFFS 16 89#define P2P_CONF_BUS_MASK (0xFF << P2P_CONF_BUS_OFFS) 90#define P2P_CONF_DEV_OFFS 24 91#define P2P_CONF_DEV_MASK (0x1F << P2P_CONF_DEV_OFFS) 92 93#define PCI_VENDORID_MRVL 0x11AB 94 95struct pcib_mbus_softc { 96 device_t sc_dev; 97 98 bus_addr_t sc_iomem_base; 99 bus_addr_t sc_iomem_size; 100 bus_addr_t sc_iomem_alloc; /* Next allocation. */ 101 102 bus_addr_t sc_ioport_base; 103 bus_addr_t sc_ioport_size; 104 bus_addr_t sc_ioport_alloc; /* Next allocation. */ 105 106 struct resource *sc_res; 107 bus_space_handle_t sc_bsh; 108 bus_space_tag_t sc_bst; 109 int sc_rid; 110 111 int sc_busnr; /* Host bridge bus number */ 112 int sc_devnr; /* Host bridge device number */ 113 114 const struct obio_pci *sc_info; 115}; 116 117static void pcib_mbus_identify(driver_t *driver, device_t parent); 118static int pcib_mbus_probe(device_t); 119static int pcib_mbus_attach(device_t); 120 121static struct resource *pcib_mbus_alloc_resource(device_t, device_t, int, int *, 122 u_long, u_long, u_long, u_int); 123static int pcib_mbus_release_resource(device_t, device_t, int, int, 124 struct resource *); 125static int pcib_mbus_read_ivar(device_t, device_t, int, uintptr_t *); 126static int pcib_mbus_write_ivar(device_t, device_t, int, uintptr_t); 127 128static int pcib_mbus_maxslots(device_t); 129static uint32_t pcib_mbus_read_config(device_t, u_int, u_int, u_int, u_int, 130 int); 131static void pcib_mbus_write_config(device_t, u_int, u_int, u_int, u_int, 132 uint32_t, int); 133static int pcib_mbus_init(struct pcib_mbus_softc *sc, int bus, int maxslot); 134static int pcib_mbus_init_bar(struct pcib_mbus_softc *sc, int bus, int slot, 135 int func, int barno); 136static void pcib_mbus_init_bridge(struct pcib_mbus_softc *sc, int bus, int slot, 137 int func); 138static int pcib_mbus_init_resources(struct pcib_mbus_softc *sc, int bus, 139 int slot, int func, int hdrtype); 140 141/* 142 * Bus interface definitions. 143 */ 144static device_method_t pcib_mbus_methods[] = { 145 /* Device interface */ 146 DEVMETHOD(device_identify, pcib_mbus_identify), 147 DEVMETHOD(device_probe, pcib_mbus_probe), 148 DEVMETHOD(device_attach, pcib_mbus_attach), 149 150 /* Bus interface */ 151 DEVMETHOD(bus_print_child, bus_generic_print_child), 152 DEVMETHOD(bus_read_ivar, pcib_mbus_read_ivar), 153 DEVMETHOD(bus_write_ivar, pcib_mbus_write_ivar), 154 DEVMETHOD(bus_alloc_resource, pcib_mbus_alloc_resource), 155 DEVMETHOD(bus_release_resource, pcib_mbus_release_resource), 156 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 157 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 158 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 159 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 160 161 /* pcib interface */ 162 DEVMETHOD(pcib_maxslots, pcib_mbus_maxslots), 163 DEVMETHOD(pcib_read_config, pcib_mbus_read_config), 164 DEVMETHOD(pcib_write_config, pcib_mbus_write_config), 165 DEVMETHOD(pcib_route_interrupt, pcib_route_interrupt), 166 167 { 0, 0 } 168}; 169 170static driver_t pcib_mbus_driver = { 171 "pcib", 172 pcib_mbus_methods, 173 sizeof(struct pcib_mbus_softc), 174}; 175 176devclass_t pcib_devclass; 177 178DRIVER_MODULE(pcib, mbus, pcib_mbus_driver, pcib_devclass, 0, 0); 179 180static struct mtx pcicfg_mtx; 181 182static inline void 183pcib_write_irq_mask(struct pcib_mbus_softc *sc, uint32_t mask) 184{ 185 186 if (!sc->sc_info->op_type != MV_TYPE_PCI) 187 return; 188 189 bus_space_write_4(sc->sc_bst, sc->sc_bsh, 190 PCIE_REG_IRQ_MASK, mask); 191} 192 193static void 194pcib_mbus_hw_cfginit(void) 195{ 196 static int opened = 0; 197 198 if (opened) 199 return; 200 201 mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN); 202 opened = 1; 203} 204 205static uint32_t 206pcib_mbus_hw_cfgread(struct pcib_mbus_softc *sc, u_int bus, u_int slot, 207 u_int func, u_int reg, int bytes) 208{ 209 uint32_t addr, data, ca, cd; 210 211 ca = (sc->sc_info->op_type != MV_TYPE_PCI) ? 212 PCIE_REG_CFG_ADDR : PCI_REG_CFG_ADDR; 213 cd = (sc->sc_info->op_type != MV_TYPE_PCI) ? 214 PCIE_REG_CFG_DATA : PCI_REG_CFG_DATA; 215 addr = PCI_CFG_ENA | PCI_CFG_BUS(bus) | PCI_CFG_DEV(slot) | 216 PCI_CFG_FUN(func) | PCI_CFG_PCIE_REG(reg); 217 218 mtx_lock_spin(&pcicfg_mtx); 219 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ca, addr); 220 221 data = ~0; 222 switch (bytes) { 223 case 1: 224 data = bus_space_read_1(sc->sc_bst, sc->sc_bsh, 225 cd + (reg & 3)); 226 break; 227 case 2: 228 data = le16toh(bus_space_read_2(sc->sc_bst, sc->sc_bsh, 229 cd + (reg & 2))); 230 break; 231 case 4: 232 data = le32toh(bus_space_read_4(sc->sc_bst, sc->sc_bsh, 233 cd)); 234 break; 235 } 236 mtx_unlock_spin(&pcicfg_mtx); 237 return (data); 238} 239 240static void 241pcib_mbus_hw_cfgwrite(struct pcib_mbus_softc *sc, u_int bus, u_int slot, 242 u_int func, u_int reg, uint32_t data, int bytes) 243{ 244 uint32_t addr, ca, cd; 245 246 ca = (sc->sc_info->op_type != MV_TYPE_PCI) ? 247 PCIE_REG_CFG_ADDR : PCI_REG_CFG_ADDR; 248 cd = (sc->sc_info->op_type != MV_TYPE_PCI) ? 249 PCIE_REG_CFG_DATA : PCI_REG_CFG_DATA; 250 addr = PCI_CFG_ENA | PCI_CFG_BUS(bus) | PCI_CFG_DEV(slot) | 251 PCI_CFG_FUN(func) | PCI_CFG_PCIE_REG(reg); 252 253 mtx_lock_spin(&pcicfg_mtx); 254 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ca, addr); 255 256 switch (bytes) { 257 case 1: 258 bus_space_write_1(sc->sc_bst, sc->sc_bsh, 259 cd + (reg & 3), data); 260 break; 261 case 2: 262 bus_space_write_2(sc->sc_bst, sc->sc_bsh, 263 cd + (reg & 2), htole16(data)); 264 break; 265 case 4: 266 bus_space_write_4(sc->sc_bst, sc->sc_bsh, 267 cd, htole32(data)); 268 break; 269 } 270 mtx_unlock_spin(&pcicfg_mtx); 271} 272 273static int 274pcib_mbus_maxslots(device_t dev) 275{ 276 struct pcib_mbus_softc *sc = device_get_softc(dev); 277 278 return ((sc->sc_info->op_type != MV_TYPE_PCI) ? 1 : PCI_SLOTMAX); 279} 280 281static uint32_t 282pcib_mbus_read_config(device_t dev, u_int bus, u_int slot, u_int func, 283 u_int reg, int bytes) 284{ 285 struct pcib_mbus_softc *sc = device_get_softc(dev); 286 287 /* Skip self */ 288 if (bus == sc->sc_busnr && slot == sc->sc_devnr) 289 return (~0U); 290 291 return (pcib_mbus_hw_cfgread(sc, bus, slot, func, reg, bytes)); 292} 293 294static void 295pcib_mbus_write_config(device_t dev, u_int bus, u_int slot, u_int func, 296 u_int reg, uint32_t val, int bytes) 297{ 298 struct pcib_mbus_softc *sc = device_get_softc(dev); 299 300 /* Skip self */ 301 if (bus == sc->sc_busnr && slot == sc->sc_devnr) 302 return; 303 304 pcib_mbus_hw_cfgwrite(sc, bus, slot, func, reg, val, bytes); 305} 306 307static void 308pcib_mbus_add_child(driver_t *driver, device_t parent, struct pcib_mbus_softc *sc) 309{ 310 device_t child; 311 int error; 312 313 /* Configure CPU decoding windows */ 314 error = decode_win_cpu_set(sc->sc_info->op_io_win_target, 315 sc->sc_info->op_io_win_attr, sc->sc_info->op_io_base, 316 sc->sc_info->op_io_size, -1); 317 if (error < 0) { 318 device_printf(parent, "Could not set up CPU decode " 319 "window for PCI IO\n"); 320 return; 321 } 322 error = decode_win_cpu_set(sc->sc_info->op_mem_win_target, 323 sc->sc_info->op_mem_win_attr, sc->sc_info->op_mem_base, 324 sc->sc_info->op_mem_size, -1); 325 if (error < 0) { 326 device_printf(parent, "Could not set up CPU decode " 327 "windows for PCI MEM\n"); 328 return; 329 } 330 331 /* Create driver instance */ 332 child = BUS_ADD_CHILD(parent, 0, driver->name, -1); 333 bus_set_resource(child, SYS_RES_MEMORY, 0, 334 sc->sc_info->op_base, sc->sc_info->op_size); 335 device_set_softc(child, sc); 336} 337 338static void 339pcib_mbus_identify(driver_t *driver, device_t parent) 340{ 341 const struct obio_pci *info = mv_pci_info; 342 struct pcib_mbus_softc *sc; 343 uint32_t control; 344 345 while (info->op_base) { 346 sc = malloc(driver->size, M_DEVBUF, M_NOWAIT | M_ZERO); 347 if (sc == NULL) { 348 device_printf(parent, "Could not allocate pcib " 349 "memory\n"); 350 break; 351 } 352 sc->sc_info = info++; 353 354 /* 355 * PCI bridge objects are instantiated immediately. PCI-Express 356 * bridges require more complicated handling depending on 357 * platform configuration. 358 */ 359 if (sc->sc_info->op_type == MV_TYPE_PCI) { 360 pcib_mbus_add_child(driver, parent, sc); 361 continue; 362 } 363 364 /* 365 * Read link configuration 366 */ 367 sc->sc_rid = 0; 368 sc->sc_res = BUS_ALLOC_RESOURCE(parent, parent, SYS_RES_MEMORY, 369 &sc->sc_rid, sc->sc_info->op_base, sc->sc_info->op_base + 370 sc->sc_info->op_size - 1, sc->sc_info->op_size, 371 RF_ACTIVE); 372 if (sc->sc_res == NULL) { 373 device_printf(parent, "Could not map pcib memory\n"); 374 break; 375 } 376 377 sc->sc_bst = rman_get_bustag(sc->sc_res); 378 sc->sc_bsh = rman_get_bushandle(sc->sc_res); 379 380 control = bus_space_read_4(sc->sc_bst, sc->sc_bsh, 381 PCIE_REG_CONTROL); 382 383 BUS_RELEASE_RESOURCE(parent, parent, SYS_RES_MEMORY, sc->sc_rid, 384 sc->sc_res); 385 386 /* 387 * If this PCI-E port (controller) is configured (by the 388 * underlying firmware) with lane width other than 1x, there 389 * are auxiliary resources defined for aggregating more width 390 * on our lane. Skip all such entries as they are not 391 * standalone ports and must not have a device object 392 * instantiated. 393 */ 394 if ((control & PCIE_CTRL_LINK1X) == 0) 395 while (info->op_base && 396 info->op_type == MV_TYPE_PCIE_AGGR_LANE) 397 info++; 398 399 pcib_mbus_add_child(driver, parent, sc); 400 } 401} 402 403static int 404pcib_mbus_probe(device_t self) 405{ 406 char buf[128]; 407 struct pcib_mbus_softc *sc; 408 const char *id, *type; 409 uint32_t val; 410 int rv = ENOENT, bus, dev; 411 412 sc = device_get_softc(self); 413 414 sc->sc_rid = 0; 415 sc->sc_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &sc->sc_rid, 416 RF_ACTIVE); 417 if (sc->sc_res == NULL) { 418 device_printf(self, "Could not map memory\n"); 419 return (ENXIO); 420 } 421 422 sc->sc_bst = rman_get_bustag(sc->sc_res); 423 sc->sc_bsh = rman_get_bushandle(sc->sc_res); 424 425 pcib_mbus_hw_cfginit(); 426 427 /* Retrieve configuration of the bridge */ 428 if (sc->sc_info->op_type == MV_TYPE_PCI) { 429 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, 430 PCI_REG_P2P_CONF); 431 bus = sc->sc_busnr = (val & P2P_CONF_BUS_MASK) >> 432 P2P_CONF_BUS_OFFS; 433 dev = sc->sc_devnr = (val & P2P_CONF_DEV_MASK) >> 434 P2P_CONF_DEV_OFFS; 435 } else { 436 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCIE_REG_STATUS); 437 bus = sc->sc_busnr = (val & STATUS_BUS_MASK) >> STATUS_BUS_OFFS; 438 dev = sc->sc_devnr = (val & STATUS_DEV_MASK) >> STATUS_DEV_OFFS; 439 } 440 441 val = pcib_mbus_hw_cfgread(sc, bus, dev, 0, PCIR_VENDOR, 2); 442 if (val != PCI_VENDORID_MRVL) 443 goto out; 444 445 val = pcib_mbus_hw_cfgread(sc, bus, dev, 0, PCIR_DEVICE, 2); 446 switch (val) { 447 case 0x5281: 448 id = "88F5281"; 449 break; 450 case 0x5182: 451 id = "88F5182"; 452 break; 453 case 0x6281: 454 id = "88F6281"; 455 break; 456 case 0x6381: 457 id = "MV78100"; 458 break; 459 default: 460 device_printf(self, "unknown Marvell PCI bridge: %x\n", val); 461 goto out; 462 } 463 464 type = "PCI"; 465 val = pcib_mbus_hw_cfgread(sc, bus, dev, 0, PCIR_CAP_PTR, 1); 466 while (val != 0) { 467 val = pcib_mbus_hw_cfgread(sc, bus, dev, 0, val, 2); 468 switch (val & 0xff) { 469 case PCIY_PCIX: 470 type = "PCI-X"; 471 break; 472 case PCIY_EXPRESS: 473 type = "PCI-Express"; 474 break; 475 } 476 val = (val >> 8) & 0xff; 477 } 478 479 snprintf(buf, sizeof(buf), "Marvell %s %s host controller", id, 480 type); 481 device_set_desc_copy(self, buf); 482 rv = BUS_PROBE_DEFAULT; 483out: 484 bus_release_resource(self, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res); 485 return (rv); 486} 487 488static int 489pcib_mbus_attach(device_t self) 490{ 491 struct pcib_mbus_softc *sc; 492 uint32_t val; 493 int err; 494 495 sc = device_get_softc(self); 496 sc->sc_dev = self; 497 498 sc->sc_rid = 0; 499 sc->sc_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &sc->sc_rid, 500 RF_ACTIVE); 501 if (sc->sc_res == NULL) { 502 device_printf(self, "Could not map memory\n"); 503 return (ENXIO); 504 } 505 sc->sc_bst = rman_get_bustag(sc->sc_res); 506 sc->sc_bsh = rman_get_bushandle(sc->sc_res); 507 508 /* Enable PCI bridge */ 509 val = pcib_mbus_hw_cfgread(sc, sc->sc_busnr, sc->sc_devnr, 0, 510 PCIR_COMMAND, 2); 511 val |= PCIM_CMD_SERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN | 512 PCIM_CMD_PORTEN; 513 pcib_mbus_hw_cfgwrite(sc, sc->sc_busnr, sc->sc_devnr, 0, 514 PCIR_COMMAND, val, 2); 515 516 sc->sc_iomem_base = sc->sc_info->op_mem_base; 517 sc->sc_iomem_size = sc->sc_info->op_mem_size; 518 sc->sc_iomem_alloc = sc->sc_info->op_mem_base; 519 520 sc->sc_ioport_base = sc->sc_info->op_io_base; 521 sc->sc_ioport_size = sc->sc_info->op_io_size; 522 sc->sc_ioport_alloc = sc->sc_info->op_io_base; 523 524 err = pcib_mbus_init(sc, sc->sc_busnr, pcib_mbus_maxslots(sc->sc_dev)); 525 if (err) 526 return(err); 527 528 device_add_child(self, "pci", -1); 529 return (bus_generic_attach(self)); 530} 531 532static int 533pcib_mbus_init_bar(struct pcib_mbus_softc *sc, int bus, int slot, int func, 534 int barno) 535{ 536 bus_addr_t *allocp, limit; 537 uint32_t addr, bar, mask, size; 538 int reg, width; 539 540 reg = PCIR_BAR(barno); 541 bar = pcib_mbus_read_config(sc->sc_dev, bus, slot, func, reg, 4); 542 if (bar == 0) 543 return (1); 544 545 /* Calculate BAR size: 64 or 32 bit (in 32-bit units) */ 546 width = ((bar & 7) == 4) ? 2 : 1; 547 548 pcib_mbus_write_config(sc->sc_dev, bus, slot, func, reg, ~0, 4); 549 size = pcib_mbus_read_config(sc->sc_dev, bus, slot, func, reg, 4); 550 551 /* Get BAR type and size */ 552 if (bar & 1) { 553 /* I/O port */ 554 allocp = &sc->sc_ioport_alloc; 555 limit = sc->sc_ioport_base + sc->sc_ioport_size; 556 size &= ~0x3; 557 if ((size & 0xffff0000) == 0) 558 size |= 0xffff0000; 559 } else { 560 /* Memory */ 561 allocp = &sc->sc_iomem_alloc; 562 limit = sc->sc_iomem_base + sc->sc_iomem_size; 563 size &= ~0xF; 564 } 565 mask = ~size; 566 size = mask + 1; 567 568 /* Sanity check (must be a power of 2) */ 569 if (size & mask) 570 return (width); 571 572 addr = (*allocp + mask) & ~mask; 573 if ((*allocp = addr + size) >= limit) 574 return (-1); 575 576 if (bootverbose) 577 printf("PCI %u:%u:%u: reg %x: size=%08x: addr=%08x\n", 578 bus, slot, func, reg, size, addr); 579 580 pcib_mbus_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4); 581 if (width == 2) 582 pcib_mbus_write_config(sc->sc_dev, bus, slot, func, reg + 4, 583 0, 4); 584 585 return (width); 586} 587 588static void 589pcib_mbus_init_bridge(struct pcib_mbus_softc *sc, int bus, int slot, int func) 590{ 591 bus_addr_t io_base, mem_base; 592 uint32_t io_limit, mem_limit; 593 int secbus; 594 595 io_base = sc->sc_info->op_io_base; 596 io_limit = io_base + sc->sc_info->op_io_size - 1; 597 mem_base = sc->sc_info->op_mem_base; 598 mem_limit = mem_base + sc->sc_info->op_mem_size - 1; 599 600 /* Configure I/O decode registers */ 601 pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_IOLIMITL_1, 602 io_limit >> 8, 1); 603 pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_IOLIMITH_1, 604 io_limit >> 16, 2); 605 606 /* Configure memory decode registers */ 607 pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_MEMBASE_1, 608 mem_base >> 16, 2); 609 pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_MEMLIMIT_1, 610 mem_limit >> 16, 2); 611 612 /* Disable memory prefetch decode */ 613 pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_PMBASEL_1, 614 0x10, 2); 615 pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_PMBASEH_1, 616 0x0, 4); 617 pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_PMLIMITL_1, 618 0xF, 2); 619 pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_PMLIMITH_1, 620 0x0, 4); 621 622 secbus = pcib_mbus_read_config(sc->sc_dev, bus, slot, func, 623 PCIR_SECBUS_1, 1); 624 625 /* Configure buses behind the bridge */ 626 pcib_mbus_init(sc, secbus, PCI_SLOTMAX); 627} 628 629static int 630pcib_mbus_init_resources(struct pcib_mbus_softc *sc, int bus, int slot, 631 int func, int hdrtype) 632{ 633 int maxbar = (hdrtype & PCIM_HDRTYPE) ? 0 : 6; 634 int bar = 0, irq, pin, i; 635 636 /* Program the base address registers */ 637 while (bar < maxbar) { 638 i = pcib_mbus_init_bar(sc, bus, slot, func, bar); 639 bar += i; 640 if (i < 0) { 641 device_printf(sc->sc_dev, 642 "PCI IO/Memory space exhausted\n"); 643 return (ENOMEM); 644 } 645 } 646 647 /* Perform interrupt routing */ 648 pin = pcib_mbus_read_config(sc->sc_dev, bus, slot, func, 649 PCIR_INTPIN, 1); 650 651 if (sc->sc_info->op_get_irq != NULL) 652 irq = sc->sc_info->op_get_irq(bus, slot, func, pin); 653 else 654 irq = sc->sc_info->op_irq; 655 656 if (irq >= 0) 657 pcib_mbus_write_config(sc->sc_dev, bus, slot, func, 658 PCIR_INTLINE, irq, 1); 659 else { 660 device_printf(sc->sc_dev, "Missing IRQ routing information " 661 "for PCI device %u:%u:%u\n", bus, slot, func); 662 return (ENXIO); 663 } 664 665 return (0); 666} 667 668static int 669pcib_mbus_init(struct pcib_mbus_softc *sc, int bus, int maxslot) 670{ 671 int slot, func, maxfunc, error; 672 uint8_t hdrtype, command, class, subclass; 673 674 for (slot = 0; slot <= maxslot; slot++) { 675 maxfunc = 0; 676 for (func = 0; func <= maxfunc; func++) { 677 hdrtype = pcib_mbus_read_config(sc->sc_dev, bus, slot, 678 func, PCIR_HDRTYPE, 1); 679 680 if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) 681 continue; 682 683 if (func == 0 && (hdrtype & PCIM_MFDEV)) 684 maxfunc = PCI_FUNCMAX; 685 686 command = pcib_mbus_read_config(sc->sc_dev, bus, slot, 687 func, PCIR_COMMAND, 1); 688 command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN); 689 pcib_mbus_write_config(sc->sc_dev, bus, slot, func, 690 PCIR_COMMAND, command, 1); 691 692 error = pcib_mbus_init_resources(sc, bus, slot, func, 693 hdrtype); 694 695 if (error) 696 return (error); 697 698 command |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN | 699 PCIM_CMD_PORTEN; 700 pcib_mbus_write_config(sc->sc_dev, bus, slot, func, 701 PCIR_COMMAND, command, 1); 702 703 /* Handle PCI-PCI bridges */ 704 class = pcib_mbus_read_config(sc->sc_dev, bus, slot, 705 func, PCIR_CLASS, 1); 706 subclass = pcib_mbus_read_config(sc->sc_dev, bus, slot, 707 func, PCIR_SUBCLASS, 1); 708 709 if (class != PCIC_BRIDGE || 710 subclass != PCIS_BRIDGE_PCI) 711 continue; 712 713 pcib_mbus_init_bridge(sc, bus, slot, func); 714 } 715 } 716 717 /* Enable all ABCD interrupts */ 718 pcib_write_irq_mask(sc, (0xF << 24)); 719 720 return (0); 721} 722 723static struct resource * 724pcib_mbus_alloc_resource(device_t dev, device_t child, int type, int *rid, 725 u_long start, u_long end, u_long count, u_int flags) 726{ 727 728 return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child, 729 type, rid, start, end, count, flags)); 730} 731 732static int 733pcib_mbus_release_resource(device_t dev, device_t child, int type, int rid, 734 struct resource *res) 735{ 736 737 return (BUS_RELEASE_RESOURCE(device_get_parent(dev), child, 738 type, rid, res)); 739} 740 741static int 742pcib_mbus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 743{ 744 struct pcib_mbus_softc *sc = device_get_softc(dev); 745 746 switch (which) { 747 case PCIB_IVAR_BUS: 748 *result = sc->sc_busnr; 749 return (0); 750 case PCIB_IVAR_DOMAIN: 751 *result = device_get_unit(dev); 752 return (0); 753 } 754 755 return (ENOENT); 756} 757 758static int 759pcib_mbus_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 760{ 761 struct pcib_mbus_softc *sc = device_get_softc(dev); 762 763 switch (which) { 764 case PCIB_IVAR_BUS: 765 sc->sc_busnr = value; 766 return (0); 767 } 768 769 return (ENOENT); 770} 771