162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Broadcom specific AMBA 362306a36Sopenharmony_ci * PCI Host 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Licensed under the GNU/GPL. See COPYING for details. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "bcma_private.h" 962306a36Sopenharmony_ci#include <linux/slab.h> 1062306a36Sopenharmony_ci#include <linux/bcma/bcma.h> 1162306a36Sopenharmony_ci#include <linux/pci.h> 1262306a36Sopenharmony_ci#include <linux/module.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_cistatic void bcma_host_pci_switch_core(struct bcma_device *core) 1562306a36Sopenharmony_ci{ 1662306a36Sopenharmony_ci int win2 = core->bus->host_is_pcie2 ? 1762306a36Sopenharmony_ci BCMA_PCIE2_BAR0_WIN2 : BCMA_PCI_BAR0_WIN2; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN, 2062306a36Sopenharmony_ci core->addr); 2162306a36Sopenharmony_ci pci_write_config_dword(core->bus->host_pci, win2, core->wrap); 2262306a36Sopenharmony_ci core->bus->mapped_core = core; 2362306a36Sopenharmony_ci bcma_debug(core->bus, "Switched to core: 0x%X\n", core->id.id); 2462306a36Sopenharmony_ci} 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/* Provides access to the requested core. Returns base offset that has to be 2762306a36Sopenharmony_ci * used. It makes use of fixed windows when possible. */ 2862306a36Sopenharmony_cistatic u16 bcma_host_pci_provide_access_to_core(struct bcma_device *core) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci switch (core->id.id) { 3162306a36Sopenharmony_ci case BCMA_CORE_CHIPCOMMON: 3262306a36Sopenharmony_ci return 3 * BCMA_CORE_SIZE; 3362306a36Sopenharmony_ci case BCMA_CORE_PCIE: 3462306a36Sopenharmony_ci return 2 * BCMA_CORE_SIZE; 3562306a36Sopenharmony_ci } 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci if (core->bus->mapped_core != core) 3862306a36Sopenharmony_ci bcma_host_pci_switch_core(core); 3962306a36Sopenharmony_ci return 0; 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci offset += bcma_host_pci_provide_access_to_core(core); 4562306a36Sopenharmony_ci return ioread8(core->bus->mmio + offset); 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci offset += bcma_host_pci_provide_access_to_core(core); 5162306a36Sopenharmony_ci return ioread16(core->bus->mmio + offset); 5262306a36Sopenharmony_ci} 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistatic u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci offset += bcma_host_pci_provide_access_to_core(core); 5762306a36Sopenharmony_ci return ioread32(core->bus->mmio + offset); 5862306a36Sopenharmony_ci} 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic void bcma_host_pci_write8(struct bcma_device *core, u16 offset, 6162306a36Sopenharmony_ci u8 value) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci offset += bcma_host_pci_provide_access_to_core(core); 6462306a36Sopenharmony_ci iowrite8(value, core->bus->mmio + offset); 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic void bcma_host_pci_write16(struct bcma_device *core, u16 offset, 6862306a36Sopenharmony_ci u16 value) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci offset += bcma_host_pci_provide_access_to_core(core); 7162306a36Sopenharmony_ci iowrite16(value, core->bus->mmio + offset); 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic void bcma_host_pci_write32(struct bcma_device *core, u16 offset, 7562306a36Sopenharmony_ci u32 value) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci offset += bcma_host_pci_provide_access_to_core(core); 7862306a36Sopenharmony_ci iowrite32(value, core->bus->mmio + offset); 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci#ifdef CONFIG_BCMA_BLOCKIO 8262306a36Sopenharmony_cistatic void bcma_host_pci_block_read(struct bcma_device *core, void *buffer, 8362306a36Sopenharmony_ci size_t count, u16 offset, u8 reg_width) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci void __iomem *addr = core->bus->mmio + offset; 8662306a36Sopenharmony_ci if (core->bus->mapped_core != core) 8762306a36Sopenharmony_ci bcma_host_pci_switch_core(core); 8862306a36Sopenharmony_ci switch (reg_width) { 8962306a36Sopenharmony_ci case sizeof(u8): 9062306a36Sopenharmony_ci ioread8_rep(addr, buffer, count); 9162306a36Sopenharmony_ci break; 9262306a36Sopenharmony_ci case sizeof(u16): 9362306a36Sopenharmony_ci WARN_ON(count & 1); 9462306a36Sopenharmony_ci ioread16_rep(addr, buffer, count >> 1); 9562306a36Sopenharmony_ci break; 9662306a36Sopenharmony_ci case sizeof(u32): 9762306a36Sopenharmony_ci WARN_ON(count & 3); 9862306a36Sopenharmony_ci ioread32_rep(addr, buffer, count >> 2); 9962306a36Sopenharmony_ci break; 10062306a36Sopenharmony_ci default: 10162306a36Sopenharmony_ci WARN_ON(1); 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic void bcma_host_pci_block_write(struct bcma_device *core, 10662306a36Sopenharmony_ci const void *buffer, size_t count, 10762306a36Sopenharmony_ci u16 offset, u8 reg_width) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci void __iomem *addr = core->bus->mmio + offset; 11062306a36Sopenharmony_ci if (core->bus->mapped_core != core) 11162306a36Sopenharmony_ci bcma_host_pci_switch_core(core); 11262306a36Sopenharmony_ci switch (reg_width) { 11362306a36Sopenharmony_ci case sizeof(u8): 11462306a36Sopenharmony_ci iowrite8_rep(addr, buffer, count); 11562306a36Sopenharmony_ci break; 11662306a36Sopenharmony_ci case sizeof(u16): 11762306a36Sopenharmony_ci WARN_ON(count & 1); 11862306a36Sopenharmony_ci iowrite16_rep(addr, buffer, count >> 1); 11962306a36Sopenharmony_ci break; 12062306a36Sopenharmony_ci case sizeof(u32): 12162306a36Sopenharmony_ci WARN_ON(count & 3); 12262306a36Sopenharmony_ci iowrite32_rep(addr, buffer, count >> 2); 12362306a36Sopenharmony_ci break; 12462306a36Sopenharmony_ci default: 12562306a36Sopenharmony_ci WARN_ON(1); 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci#endif 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistatic u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci if (core->bus->mapped_core != core) 13362306a36Sopenharmony_ci bcma_host_pci_switch_core(core); 13462306a36Sopenharmony_ci return ioread32(core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset); 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic void bcma_host_pci_awrite32(struct bcma_device *core, u16 offset, 13862306a36Sopenharmony_ci u32 value) 13962306a36Sopenharmony_ci{ 14062306a36Sopenharmony_ci if (core->bus->mapped_core != core) 14162306a36Sopenharmony_ci bcma_host_pci_switch_core(core); 14262306a36Sopenharmony_ci iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset); 14362306a36Sopenharmony_ci} 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_cistatic const struct bcma_host_ops bcma_host_pci_ops = { 14662306a36Sopenharmony_ci .read8 = bcma_host_pci_read8, 14762306a36Sopenharmony_ci .read16 = bcma_host_pci_read16, 14862306a36Sopenharmony_ci .read32 = bcma_host_pci_read32, 14962306a36Sopenharmony_ci .write8 = bcma_host_pci_write8, 15062306a36Sopenharmony_ci .write16 = bcma_host_pci_write16, 15162306a36Sopenharmony_ci .write32 = bcma_host_pci_write32, 15262306a36Sopenharmony_ci#ifdef CONFIG_BCMA_BLOCKIO 15362306a36Sopenharmony_ci .block_read = bcma_host_pci_block_read, 15462306a36Sopenharmony_ci .block_write = bcma_host_pci_block_write, 15562306a36Sopenharmony_ci#endif 15662306a36Sopenharmony_ci .aread32 = bcma_host_pci_aread32, 15762306a36Sopenharmony_ci .awrite32 = bcma_host_pci_awrite32, 15862306a36Sopenharmony_ci}; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic int bcma_host_pci_probe(struct pci_dev *dev, 16162306a36Sopenharmony_ci const struct pci_device_id *id) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci struct bcma_bus *bus; 16462306a36Sopenharmony_ci int err = -ENOMEM; 16562306a36Sopenharmony_ci u32 val; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci /* Alloc */ 16862306a36Sopenharmony_ci bus = kzalloc(sizeof(*bus), GFP_KERNEL); 16962306a36Sopenharmony_ci if (!bus) 17062306a36Sopenharmony_ci goto out; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci /* Basic PCI configuration */ 17362306a36Sopenharmony_ci err = pci_enable_device(dev); 17462306a36Sopenharmony_ci if (err) 17562306a36Sopenharmony_ci goto err_kfree_bus; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci err = pci_request_regions(dev, "bcma-pci-bridge"); 17862306a36Sopenharmony_ci if (err) 17962306a36Sopenharmony_ci goto err_pci_disable; 18062306a36Sopenharmony_ci pci_set_master(dev); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci /* Disable the RETRY_TIMEOUT register (0x41) to keep 18362306a36Sopenharmony_ci * PCI Tx retries from interfering with C3 CPU state */ 18462306a36Sopenharmony_ci pci_read_config_dword(dev, 0x40, &val); 18562306a36Sopenharmony_ci if ((val & 0x0000ff00) != 0) 18662306a36Sopenharmony_ci pci_write_config_dword(dev, 0x40, val & 0xffff00ff); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci /* SSB needed additional powering up, do we have any AMBA PCI cards? */ 18962306a36Sopenharmony_ci if (!pci_is_pcie(dev)) { 19062306a36Sopenharmony_ci bcma_err(bus, "PCI card detected, they are not supported.\n"); 19162306a36Sopenharmony_ci err = -ENXIO; 19262306a36Sopenharmony_ci goto err_pci_release_regions; 19362306a36Sopenharmony_ci } 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci bus->dev = &dev->dev; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci /* Map MMIO */ 19862306a36Sopenharmony_ci err = -ENOMEM; 19962306a36Sopenharmony_ci bus->mmio = pci_iomap(dev, 0, ~0UL); 20062306a36Sopenharmony_ci if (!bus->mmio) 20162306a36Sopenharmony_ci goto err_pci_release_regions; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* Host specific */ 20462306a36Sopenharmony_ci bus->host_pci = dev; 20562306a36Sopenharmony_ci bus->hosttype = BCMA_HOSTTYPE_PCI; 20662306a36Sopenharmony_ci bus->ops = &bcma_host_pci_ops; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci bus->boardinfo.vendor = bus->host_pci->subsystem_vendor; 20962306a36Sopenharmony_ci bus->boardinfo.type = bus->host_pci->subsystem_device; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci /* Initialize struct, detect chip */ 21262306a36Sopenharmony_ci bcma_init_bus(bus); 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci /* Scan bus to find out generation of PCIe core */ 21562306a36Sopenharmony_ci err = bcma_bus_scan(bus); 21662306a36Sopenharmony_ci if (err) 21762306a36Sopenharmony_ci goto err_pci_unmap_mmio; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci if (bcma_find_core(bus, BCMA_CORE_PCIE2)) 22062306a36Sopenharmony_ci bus->host_is_pcie2 = true; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci /* Register */ 22362306a36Sopenharmony_ci err = bcma_bus_register(bus); 22462306a36Sopenharmony_ci if (err) 22562306a36Sopenharmony_ci goto err_unregister_cores; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci pci_set_drvdata(dev, bus); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ciout: 23062306a36Sopenharmony_ci return err; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_cierr_unregister_cores: 23362306a36Sopenharmony_ci bcma_unregister_cores(bus); 23462306a36Sopenharmony_cierr_pci_unmap_mmio: 23562306a36Sopenharmony_ci pci_iounmap(dev, bus->mmio); 23662306a36Sopenharmony_cierr_pci_release_regions: 23762306a36Sopenharmony_ci pci_release_regions(dev); 23862306a36Sopenharmony_cierr_pci_disable: 23962306a36Sopenharmony_ci pci_disable_device(dev); 24062306a36Sopenharmony_cierr_kfree_bus: 24162306a36Sopenharmony_ci kfree(bus); 24262306a36Sopenharmony_ci return err; 24362306a36Sopenharmony_ci} 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistatic void bcma_host_pci_remove(struct pci_dev *dev) 24662306a36Sopenharmony_ci{ 24762306a36Sopenharmony_ci struct bcma_bus *bus = pci_get_drvdata(dev); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci bcma_bus_unregister(bus); 25062306a36Sopenharmony_ci pci_iounmap(dev, bus->mmio); 25162306a36Sopenharmony_ci pci_release_regions(dev); 25262306a36Sopenharmony_ci pci_disable_device(dev); 25362306a36Sopenharmony_ci kfree(bus); 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 25762306a36Sopenharmony_cistatic int bcma_host_pci_suspend(struct device *dev) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci struct bcma_bus *bus = dev_get_drvdata(dev); 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci bus->mapped_core = NULL; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci return bcma_bus_suspend(bus); 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic int bcma_host_pci_resume(struct device *dev) 26762306a36Sopenharmony_ci{ 26862306a36Sopenharmony_ci struct bcma_bus *bus = dev_get_drvdata(dev); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci return bcma_bus_resume(bus); 27162306a36Sopenharmony_ci} 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend, 27462306a36Sopenharmony_ci bcma_host_pci_resume); 27562306a36Sopenharmony_ci#define BCMA_PM_OPS (&bcma_pm_ops) 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci#else /* CONFIG_PM_SLEEP */ 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci#define BCMA_PM_OPS NULL 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci#endif /* CONFIG_PM_SLEEP */ 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic const struct pci_device_id bcma_pci_bridge_tbl[] = { 28462306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, 28562306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4313) }, 28662306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) }, /* 0xa8d8 */ 28762306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, 28862306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, 28962306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, 29062306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) }, 29162306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, 29262306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4360) }, 29362306a36Sopenharmony_ci { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_DELL, 0x0016) }, 29462306a36Sopenharmony_ci { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_DELL, 0x0018) }, 29562306a36Sopenharmony_ci { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_FOXCONN, 0xe092) }, 29662306a36Sopenharmony_ci { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_HP, 0x804a) }, 29762306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a0) }, 29862306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) }, 29962306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) }, 30062306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43b1) }, 30162306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, 30262306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) }, /* 0xa8db, BCM43217 (sic!) */ 30362306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43228) }, /* 0xa8dc */ 30462306a36Sopenharmony_ci { 0, }, 30562306a36Sopenharmony_ci}; 30662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_cistatic struct pci_driver bcma_pci_bridge_driver = { 30962306a36Sopenharmony_ci .name = "bcma-pci-bridge", 31062306a36Sopenharmony_ci .id_table = bcma_pci_bridge_tbl, 31162306a36Sopenharmony_ci .probe = bcma_host_pci_probe, 31262306a36Sopenharmony_ci .remove = bcma_host_pci_remove, 31362306a36Sopenharmony_ci .driver.pm = BCMA_PM_OPS, 31462306a36Sopenharmony_ci}; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ciint __init bcma_host_pci_init(void) 31762306a36Sopenharmony_ci{ 31862306a36Sopenharmony_ci return pci_register_driver(&bcma_pci_bridge_driver); 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_civoid __exit bcma_host_pci_exit(void) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci pci_unregister_driver(&bcma_pci_bridge_driver); 32462306a36Sopenharmony_ci} 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci/************************************************** 32762306a36Sopenharmony_ci * Runtime ops for drivers. 32862306a36Sopenharmony_ci **************************************************/ 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci/* See also pcicore_up */ 33162306a36Sopenharmony_civoid bcma_host_pci_up(struct bcma_bus *bus) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci if (bus->hosttype != BCMA_HOSTTYPE_PCI) 33462306a36Sopenharmony_ci return; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci if (bus->host_is_pcie2) 33762306a36Sopenharmony_ci bcma_core_pcie2_up(&bus->drv_pcie2); 33862306a36Sopenharmony_ci else 33962306a36Sopenharmony_ci bcma_core_pci_up(&bus->drv_pci[0]); 34062306a36Sopenharmony_ci} 34162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(bcma_host_pci_up); 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci/* See also pcicore_down */ 34462306a36Sopenharmony_civoid bcma_host_pci_down(struct bcma_bus *bus) 34562306a36Sopenharmony_ci{ 34662306a36Sopenharmony_ci if (bus->hosttype != BCMA_HOSTTYPE_PCI) 34762306a36Sopenharmony_ci return; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci if (!bus->host_is_pcie2) 35062306a36Sopenharmony_ci bcma_core_pci_down(&bus->drv_pci[0]); 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(bcma_host_pci_down); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci/* See also si_pci_setup */ 35562306a36Sopenharmony_ciint bcma_host_pci_irq_ctl(struct bcma_bus *bus, struct bcma_device *core, 35662306a36Sopenharmony_ci bool enable) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci struct pci_dev *pdev; 35962306a36Sopenharmony_ci u32 coremask, tmp; 36062306a36Sopenharmony_ci int err = 0; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci if (bus->hosttype != BCMA_HOSTTYPE_PCI) { 36362306a36Sopenharmony_ci /* This bcma device is not on a PCI host-bus. So the IRQs are 36462306a36Sopenharmony_ci * not routed through the PCI core. 36562306a36Sopenharmony_ci * So we must not enable routing through the PCI core. */ 36662306a36Sopenharmony_ci goto out; 36762306a36Sopenharmony_ci } 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci pdev = bus->host_pci; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); 37262306a36Sopenharmony_ci if (err) 37362306a36Sopenharmony_ci goto out; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci coremask = BIT(core->core_index) << 8; 37662306a36Sopenharmony_ci if (enable) 37762306a36Sopenharmony_ci tmp |= coremask; 37862306a36Sopenharmony_ci else 37962306a36Sopenharmony_ci tmp &= ~coremask; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp); 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ciout: 38462306a36Sopenharmony_ci return err; 38562306a36Sopenharmony_ci} 38662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(bcma_host_pci_irq_ctl); 387