1 /* 2 * Broadcom specific AMBA 3 * PCI Core in hostmode 4 * 5 * Copyright 2005 - 2011, Broadcom Corporation 6 * Copyright 2006, 2007, Michael Buesch <m@bues.ch> 7 * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de> 8 * 9 * Licensed under the GNU/GPL. See COPYING for details. 10 */ 11 12 #include "bcma_private.h" 13 #include <linux/pci.h> 14 #include <linux/export.h> 15 #include <linux/bcma/bcma.h> 16 #include <asm/paccess.h> 17 18 /* Probe a 32bit value on the bus and catch bus exceptions. 19 * Returns nonzero on a bus exception. 20 * This is MIPS specific */ 21 #define mips_busprobe32(val, addr) get_dbe((val), ((u32 *)(addr))) 22 23 /* Assume one-hot slot wiring */ 24 #define BCMA_PCI_SLOT_MAX 16 25 #define PCI_CONFIG_SPACE_SIZE 256 26 27 bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) 28 { 29 struct bcma_bus *bus = pc->core->bus; 30 u16 chipid_top; 31 u32 tmp; 32 33 chipid_top = (bus->chipinfo.id & 0xFF00); 34 if (chipid_top != 0x4700 && 35 chipid_top != 0x5300) 36 return false; 37 38 bcma_core_enable(pc->core, 0); 39 40 return !mips_busprobe32(tmp, pc->core->io_addr); 41 } 42 43 static u32 bcma_pcie_read_config(struct bcma_drv_pci *pc, u32 address) 44 { 45 pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_ADDR, address); 46 pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_ADDR); 47 return pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_DATA); 48 } 49 50 static void bcma_pcie_write_config(struct bcma_drv_pci *pc, u32 address, 51 u32 data) 52 { 53 pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_ADDR, address); 54 pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_ADDR); 55 pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_DATA, data); 56 } 57 58 static u32 bcma_get_cfgspace_addr(struct bcma_drv_pci *pc, unsigned int dev, 59 unsigned int func, unsigned int off) 60 { 61 u32 addr = 0; 62 63 /* Issue config commands only when the data link is up (atleast 64 * one external pcie device is present). 65 */ 66 if (dev >= 2 || !(bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_LSREG) 67 & BCMA_CORE_PCI_DLLP_LSREG_LINKUP)) 68 goto out; 69 70 /* Type 0 transaction */ 71 /* Slide the PCI window to the appropriate slot */ 72 pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0); 73 /* Calculate the address */ 74 addr = pc->host_controller->host_cfg_addr; 75 addr |= (dev << BCMA_CORE_PCI_CFG_SLOT_SHIFT); 76 addr |= (func << BCMA_CORE_PCI_CFG_FUN_SHIFT); 77 addr |= (off & ~3); 78 79 out: 80 return addr; 81 } 82 83 static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev, 84 unsigned int func, unsigned int off, 85 void *buf, int len) 86 { 87 int err = -EINVAL; 88 u32 addr, val; 89 void __iomem *mmio = 0; 90 91 WARN_ON(!pc->hostmode); 92 if (unlikely(len != 1 && len != 2 && len != 4)) 93 goto out; 94 if (dev == 0) { 95 /* we support only two functions on device 0 */ 96 if (func > 1) 97 return -EINVAL; 98 99 /* accesses to config registers with offsets >= 256 100 * requires indirect access. 101 */ 102 if (off >= PCI_CONFIG_SPACE_SIZE) { 103 addr = (func << 12); 104 addr |= (off & 0x0FFF); 105 val = bcma_pcie_read_config(pc, addr); 106 } else { 107 addr = BCMA_CORE_PCI_PCICFG0; 108 addr |= (func << 8); 109 addr |= (off & 0xfc); 110 val = pcicore_read32(pc, addr); 111 } 112 } else { 113 addr = bcma_get_cfgspace_addr(pc, dev, func, off); 114 if (unlikely(!addr)) 115 goto out; 116 err = -ENOMEM; 117 mmio = ioremap_nocache(addr, sizeof(val)); 118 if (!mmio) 119 goto out; 120 121 if (mips_busprobe32(val, mmio)) { 122 val = 0xffffffff; 123 goto unmap; 124 } 125 126 val = readl(mmio); 127 } 128 val >>= (8 * (off & 3)); 129 130 switch (len) { 131 case 1: 132 *((u8 *)buf) = (u8)val; 133 break; 134 case 2: 135 *((u16 *)buf) = (u16)val; 136 break; 137 case 4: 138 *((u32 *)buf) = (u32)val; 139 break; 140 } 141 err = 0; 142 unmap: 143 if (mmio) 144 iounmap(mmio); 145 out: 146 return err; 147 } 148 149 static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev, 150 unsigned int func, unsigned int off, 151 const void *buf, int len) 152 { 153 int err = -EINVAL; 154 u32 addr = 0, val = 0; 155 void __iomem *mmio = 0; 156 u16 chipid = pc->core->bus->chipinfo.id; 157 158 WARN_ON(!pc->hostmode); 159 if (unlikely(len != 1 && len != 2 && len != 4)) 160 goto out; 161 if (dev == 0) { 162 /* accesses to config registers with offsets >= 256 163 * requires indirect access. 164 */ 165 if (off < PCI_CONFIG_SPACE_SIZE) { 166 addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0; 167 addr |= (func << 8); 168 addr |= (off & 0xfc); 169 mmio = ioremap_nocache(addr, sizeof(val)); 170 if (!mmio) 171 goto out; 172 } 173 } else { 174 addr = bcma_get_cfgspace_addr(pc, dev, func, off); 175 if (unlikely(!addr)) 176 goto out; 177 err = -ENOMEM; 178 mmio = ioremap_nocache(addr, sizeof(val)); 179 if (!mmio) 180 goto out; 181 182 if (mips_busprobe32(val, mmio)) { 183 val = 0xffffffff; 184 goto unmap; 185 } 186 } 187 188 switch (len) { 189 case 1: 190 val = readl(mmio); 191 val &= ~(0xFF << (8 * (off & 3))); 192 val |= *((const u8 *)buf) << (8 * (off & 3)); 193 break; 194 case 2: 195 val = readl(mmio); 196 val &= ~(0xFFFF << (8 * (off & 3))); 197 val |= *((const u16 *)buf) << (8 * (off & 3)); 198 break; 199 case 4: 200 val = *((const u32 *)buf); 201 break; 202 } 203 if (dev == 0 && !addr) { 204 /* accesses to config registers with offsets >= 256 205 * requires indirect access. 206 */ 207 addr = (func << 12); 208 addr |= (off & 0x0FFF); 209 bcma_pcie_write_config(pc, addr, val); 210 } else { 211 writel(val, mmio); 212 213 if (chipid == BCMA_CHIP_ID_BCM4716 || 214 chipid == BCMA_CHIP_ID_BCM4748) 215 readl(mmio); 216 } 217 218 err = 0; 219 unmap: 220 if (mmio) 221 iounmap(mmio); 222 out: 223 return err; 224 } 225 226 static int bcma_core_pci_hostmode_read_config(struct pci_bus *bus, 227 unsigned int devfn, 228 int reg, int size, u32 *val) 229 { 230 unsigned long flags; 231 int err; 232 struct bcma_drv_pci *pc; 233 struct bcma_drv_pci_host *pc_host; 234 235 pc_host = container_of(bus->ops, struct bcma_drv_pci_host, pci_ops); 236 pc = pc_host->pdev; 237 238 spin_lock_irqsave(&pc_host->cfgspace_lock, flags); 239 err = bcma_extpci_read_config(pc, PCI_SLOT(devfn), 240 PCI_FUNC(devfn), reg, val, size); 241 spin_unlock_irqrestore(&pc_host->cfgspace_lock, flags); 242 243 return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; 244 } 245 246 static int bcma_core_pci_hostmode_write_config(struct pci_bus *bus, 247 unsigned int devfn, 248 int reg, int size, u32 val) 249 { 250 unsigned long flags; 251 int err; 252 struct bcma_drv_pci *pc; 253 struct bcma_drv_pci_host *pc_host; 254 255 pc_host = container_of(bus->ops, struct bcma_drv_pci_host, pci_ops); 256 pc = pc_host->pdev; 257 258 spin_lock_irqsave(&pc_host->cfgspace_lock, flags); 259 err = bcma_extpci_write_config(pc, PCI_SLOT(devfn), 260 PCI_FUNC(devfn), reg, &val, size); 261 spin_unlock_irqrestore(&pc_host->cfgspace_lock, flags); 262 263 return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; 264 } 265 266 /* return cap_offset if requested capability exists in the PCI config space */ 267 static u8 bcma_find_pci_capability(struct bcma_drv_pci *pc, unsigned int dev, 268 unsigned int func, u8 req_cap_id, 269 unsigned char *buf, u32 *buflen) 270 { 271 u8 cap_id; 272 u8 cap_ptr = 0; 273 u32 bufsize; 274 u8 byte_val; 275 276 /* check for Header type 0 */ 277 bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val, 278 sizeof(u8)); 279 if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL) 280 return cap_ptr; 281 282 /* check if the capability pointer field exists */ 283 bcma_extpci_read_config(pc, dev, func, PCI_STATUS, &byte_val, 284 sizeof(u8)); 285 if (!(byte_val & PCI_STATUS_CAP_LIST)) 286 return cap_ptr; 287 288 /* check if the capability pointer is 0x00 */ 289 bcma_extpci_read_config(pc, dev, func, PCI_CAPABILITY_LIST, &cap_ptr, 290 sizeof(u8)); 291 if (cap_ptr == 0x00) 292 return cap_ptr; 293 294 /* loop thr'u the capability list and see if the requested capabilty 295 * exists */ 296 bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id, sizeof(u8)); 297 while (cap_id != req_cap_id) { 298 bcma_extpci_read_config(pc, dev, func, cap_ptr + 1, &cap_ptr, 299 sizeof(u8)); 300 if (cap_ptr == 0x00) 301 return cap_ptr; 302 bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id, 303 sizeof(u8)); 304 } 305 306 /* found the caller requested capability */ 307 if ((buf != NULL) && (buflen != NULL)) { 308 u8 cap_data; 309 310 bufsize = *buflen; 311 if (!bufsize) 312 return cap_ptr; 313 314 *buflen = 0; 315 316 /* copy the cpability data excluding cap ID and next ptr */ 317 cap_data = cap_ptr + 2; 318 if ((bufsize + cap_data) > PCI_CONFIG_SPACE_SIZE) 319 bufsize = PCI_CONFIG_SPACE_SIZE - cap_data; 320 *buflen = bufsize; 321 while (bufsize--) { 322 bcma_extpci_read_config(pc, dev, func, cap_data, buf, 323 sizeof(u8)); 324 cap_data++; 325 buf++; 326 } 327 } 328 329 return cap_ptr; 330 } 331 332 /* If the root port is capable of returning Config Request 333 * Retry Status (CRS) Completion Status to software then 334 * enable the feature. 335 */ 336 static void bcma_core_pci_enable_crs(struct bcma_drv_pci *pc) 337 { 338 struct bcma_bus *bus = pc->core->bus; 339 u8 cap_ptr, root_ctrl, root_cap, dev; 340 u16 val16; 341 int i; 342 343 cap_ptr = bcma_find_pci_capability(pc, 0, 0, PCI_CAP_ID_EXP, NULL, 344 NULL); 345 root_cap = cap_ptr + PCI_EXP_RTCAP; 346 bcma_extpci_read_config(pc, 0, 0, root_cap, &val16, sizeof(u16)); 347 if (val16 & BCMA_CORE_PCI_RC_CRS_VISIBILITY) { 348 /* Enable CRS software visibility */ 349 root_ctrl = cap_ptr + PCI_EXP_RTCTL; 350 val16 = PCI_EXP_RTCTL_CRSSVE; 351 bcma_extpci_read_config(pc, 0, 0, root_ctrl, &val16, 352 sizeof(u16)); 353 354 /* Initiate a configuration request to read the vendor id 355 * field of the device function's config space header after 356 * 100 ms wait time from the end of Reset. If the device is 357 * not done with its internal initialization, it must at 358 * least return a completion TLP, with a completion status 359 * of "Configuration Request Retry Status (CRS)". The root 360 * complex must complete the request to the host by returning 361 * a read-data value of 0001h for the Vendor ID field and 362 * all 1s for any additional bytes included in the request. 363 * Poll using the config reads for max wait time of 1 sec or 364 * until we receive the successful completion status. Repeat 365 * the procedure for all the devices. 366 */ 367 for (dev = 1; dev < BCMA_PCI_SLOT_MAX; dev++) { 368 for (i = 0; i < 100000; i++) { 369 bcma_extpci_read_config(pc, dev, 0, 370 PCI_VENDOR_ID, &val16, 371 sizeof(val16)); 372 if (val16 != 0x1) 373 break; 374 udelay(10); 375 } 376 if (val16 == 0x1) 377 bcma_err(bus, "PCI: Broken device in slot %d\n", 378 dev); 379 } 380 } 381 } 382 383 void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) 384 { 385 struct bcma_bus *bus = pc->core->bus; 386 struct bcma_drv_pci_host *pc_host; 387 u32 tmp; 388 u32 pci_membase_1G; 389 unsigned long io_map_base; 390 391 bcma_info(bus, "PCIEcore in host mode found\n"); 392 393 if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) { 394 bcma_info(bus, "This PCIE core is disabled and not working\n"); 395 return; 396 } 397 398 pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL); 399 if (!pc_host) { 400 bcma_err(bus, "can not allocate memory"); 401 return; 402 } 403 404 pc->host_controller = pc_host; 405 pc_host->pci_controller.io_resource = &pc_host->io_resource; 406 pc_host->pci_controller.mem_resource = &pc_host->mem_resource; 407 pc_host->pci_controller.pci_ops = &pc_host->pci_ops; 408 pc_host->pdev = pc; 409 410 pci_membase_1G = BCMA_SOC_PCI_DMA; 411 pc_host->host_cfg_addr = BCMA_SOC_PCI_CFG; 412 413 pc_host->pci_ops.read = bcma_core_pci_hostmode_read_config; 414 pc_host->pci_ops.write = bcma_core_pci_hostmode_write_config; 415 416 pc_host->mem_resource.name = "BCMA PCIcore external memory", 417 pc_host->mem_resource.start = BCMA_SOC_PCI_DMA; 418 pc_host->mem_resource.end = BCMA_SOC_PCI_DMA + BCMA_SOC_PCI_DMA_SZ - 1; 419 pc_host->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED; 420 421 pc_host->io_resource.name = "BCMA PCIcore external I/O", 422 pc_host->io_resource.start = 0x100; 423 pc_host->io_resource.end = 0x7FF; 424 pc_host->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED; 425 426 /* Reset RC */ 427 usleep_range(3000, 5000); 428 pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE); 429 usleep_range(1000, 2000); 430 pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST | 431 BCMA_CORE_PCI_CTL_RST_OE); 432 433 /* 64 MB I/O access window. On 4716, use 434 * sbtopcie0 to access the device registers. We 435 * can't use address match 2 (1 GB window) region 436 * as mips can't generate 64-bit address on the 437 * backplane. 438 */ 439 if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4716 || 440 bus->chipinfo.id == BCMA_CHIP_ID_BCM4748) { 441 pc_host->mem_resource.start = BCMA_SOC_PCI_MEM; 442 pc_host->mem_resource.end = BCMA_SOC_PCI_MEM + 443 BCMA_SOC_PCI_MEM_SZ - 1; 444 pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, 445 BCMA_CORE_PCI_SBTOPCI_MEM | BCMA_SOC_PCI_MEM); 446 } else if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) { 447 tmp = BCMA_CORE_PCI_SBTOPCI_MEM; 448 tmp |= BCMA_CORE_PCI_SBTOPCI_PREF; 449 tmp |= BCMA_CORE_PCI_SBTOPCI_BURST; 450 if (pc->core->core_unit == 0) { 451 pc_host->mem_resource.start = BCMA_SOC_PCI_MEM; 452 pc_host->mem_resource.end = BCMA_SOC_PCI_MEM + 453 BCMA_SOC_PCI_MEM_SZ - 1; 454 pc_host->io_resource.start = 0x100; 455 pc_host->io_resource.end = 0x47F; 456 pci_membase_1G = BCMA_SOC_PCIE_DMA_H32; 457 pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, 458 tmp | BCMA_SOC_PCI_MEM); 459 } else if (pc->core->core_unit == 1) { 460 pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM; 461 pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM + 462 BCMA_SOC_PCI_MEM_SZ - 1; 463 pc_host->io_resource.start = 0x480; 464 pc_host->io_resource.end = 0x7FF; 465 pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32; 466 pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG; 467 pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, 468 tmp | BCMA_SOC_PCI1_MEM); 469 } 470 } else 471 pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, 472 BCMA_CORE_PCI_SBTOPCI_IO); 473 474 /* 64 MB configuration access window */ 475 pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0); 476 477 /* 1 GB memory access window */ 478 pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI2, 479 BCMA_CORE_PCI_SBTOPCI_MEM | pci_membase_1G); 480 481 482 /* As per PCI Express Base Spec 1.1 we need to wait for 483 * at least 100 ms from the end of a reset (cold/warm/hot) 484 * before issuing configuration requests to PCI Express 485 * devices. 486 */ 487 msleep(100); 488 489 bcma_core_pci_enable_crs(pc); 490 491 /* Enable PCI bridge BAR0 memory & master access */ 492 tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; 493 bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp)); 494 495 /* Enable PCI interrupts */ 496 pcicore_write32(pc, BCMA_CORE_PCI_IMASK, BCMA_CORE_PCI_IMASK_INTA); 497 498 /* Ok, ready to run, register it to the system. 499 * The following needs change, if we want to port hostmode 500 * to non-MIPS platform. */ 501 io_map_base = (unsigned long)ioremap_nocache(pc_host->mem_resource.start, 502 resource_size(&pc_host->mem_resource)); 503 pc_host->pci_controller.io_map_base = io_map_base; 504 set_io_port_base(pc_host->pci_controller.io_map_base); 505 /* Give some time to the PCI controller to configure itself with the new 506 * values. Not waiting at this point causes crashes of the machine. */ 507 usleep_range(10000, 15000); 508 register_pci_controller(&pc_host->pci_controller); 509 return; 510 } 511 512 /* Early PCI fixup for a device on the PCI-core bridge. */ 513 static void bcma_core_pci_fixup_pcibridge(struct pci_dev *dev) 514 { 515 if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { 516 /* This is not a device on the PCI-core bridge. */ 517 return; 518 } 519 if (PCI_SLOT(dev->devfn) != 0) 520 return; 521 522 pr_info("PCI: Fixing up bridge %s\n", pci_name(dev)); 523 524 /* Enable PCI bridge bus mastering and memory space */ 525 pci_set_master(dev); 526 if (pcibios_enable_device(dev, ~0) < 0) { 527 pr_err("PCI: BCMA bridge enable failed\n"); 528 return; 529 } 530 531 /* Enable PCI bridge BAR1 prefetch and burst */ 532 pci_write_config_dword(dev, BCMA_PCI_BAR1_CONTROL, 3); 533 } 534 DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_pcibridge); 535 536 /* Early PCI fixup for all PCI-cores to set the correct memory address. */ 537 static void bcma_core_pci_fixup_addresses(struct pci_dev *dev) 538 { 539 struct resource *res; 540 int pos, err; 541 542 if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { 543 /* This is not a device on the PCI-core bridge. */ 544 return; 545 } 546 if (PCI_SLOT(dev->devfn) == 0) 547 return; 548 549 pr_info("PCI: Fixing up addresses %s\n", pci_name(dev)); 550 551 for (pos = 0; pos < 6; pos++) { 552 res = &dev->resource[pos]; 553 if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM)) { 554 err = pci_assign_resource(dev, pos); 555 if (err) 556 pr_err("PCI: Problem fixing up the addresses on %s\n", 557 pci_name(dev)); 558 } 559 } 560 } 561 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses); 562 563 /* This function is called when doing a pci_enable_device(). 564 * We must first check if the device is a device on the PCI-core bridge. */ 565 int bcma_core_pci_plat_dev_init(struct pci_dev *dev) 566 { 567 struct bcma_drv_pci_host *pc_host; 568 569 if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { 570 /* This is not a device on the PCI-core bridge. */ 571 return -ENODEV; 572 } 573 pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host, 574 pci_ops); 575 576 pr_info("PCI: Fixing up device %s\n", pci_name(dev)); 577 578 /* Fix up interrupt lines */ 579 dev->irq = bcma_core_mips_irq(pc_host->pdev->core) + 2; 580 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); 581 582 return 0; 583 } 584 EXPORT_SYMBOL(bcma_core_pci_plat_dev_init); 585 586 /* PCI device IRQ mapping. */ 587 int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev) 588 { 589 struct bcma_drv_pci_host *pc_host; 590 591 if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { 592 /* This is not a device on the PCI-core bridge. */ 593 return -ENODEV; 594 } 595 596 pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host, 597 pci_ops); 598 return bcma_core_mips_irq(pc_host->pdev->core) + 2; 599 } 600 EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq); 601