18369ae33SRafał Miłecki /* 28369ae33SRafał Miłecki * Broadcom specific AMBA 38369ae33SRafał Miłecki * PCI Host 48369ae33SRafał Miłecki * 58369ae33SRafał Miłecki * Licensed under the GNU/GPL. See COPYING for details. 68369ae33SRafał Miłecki */ 78369ae33SRafał Miłecki 88369ae33SRafał Miłecki #include "bcma_private.h" 98369ae33SRafał Miłecki #include <linux/bcma/bcma.h> 108369ae33SRafał Miłecki #include <linux/pci.h> 118369ae33SRafał Miłecki 128369ae33SRafał Miłecki static void bcma_host_pci_switch_core(struct bcma_device *core) 138369ae33SRafał Miłecki { 148369ae33SRafał Miłecki pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN, 158369ae33SRafał Miłecki core->addr); 168369ae33SRafał Miłecki pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2, 178369ae33SRafał Miłecki core->wrap); 188369ae33SRafał Miłecki core->bus->mapped_core = core; 198369ae33SRafał Miłecki pr_debug("Switched to core: 0x%X\n", core->id.id); 208369ae33SRafał Miłecki } 218369ae33SRafał Miłecki 228369ae33SRafał Miłecki static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset) 238369ae33SRafał Miłecki { 248369ae33SRafał Miłecki if (core->bus->mapped_core != core) 258369ae33SRafał Miłecki bcma_host_pci_switch_core(core); 268369ae33SRafał Miłecki return ioread8(core->bus->mmio + offset); 278369ae33SRafał Miłecki } 288369ae33SRafał Miłecki 298369ae33SRafał Miłecki static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset) 308369ae33SRafał Miłecki { 318369ae33SRafał Miłecki if (core->bus->mapped_core != core) 328369ae33SRafał Miłecki bcma_host_pci_switch_core(core); 338369ae33SRafał Miłecki return ioread16(core->bus->mmio + offset); 348369ae33SRafał Miłecki } 358369ae33SRafał Miłecki 368369ae33SRafał Miłecki static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset) 378369ae33SRafał Miłecki { 388369ae33SRafał Miłecki if (core->bus->mapped_core != core) 398369ae33SRafał Miłecki bcma_host_pci_switch_core(core); 408369ae33SRafał Miłecki return ioread32(core->bus->mmio + offset); 418369ae33SRafał Miłecki } 428369ae33SRafał Miłecki 438369ae33SRafał Miłecki static void bcma_host_pci_write8(struct bcma_device *core, u16 offset, 448369ae33SRafał Miłecki u8 value) 458369ae33SRafał Miłecki { 468369ae33SRafał Miłecki if (core->bus->mapped_core != core) 478369ae33SRafał Miłecki bcma_host_pci_switch_core(core); 488369ae33SRafał Miłecki iowrite8(value, core->bus->mmio + offset); 498369ae33SRafał Miłecki } 508369ae33SRafał Miłecki 518369ae33SRafał Miłecki static void bcma_host_pci_write16(struct bcma_device *core, u16 offset, 528369ae33SRafał Miłecki u16 value) 538369ae33SRafał Miłecki { 548369ae33SRafał Miłecki if (core->bus->mapped_core != core) 558369ae33SRafał Miłecki bcma_host_pci_switch_core(core); 568369ae33SRafał Miłecki iowrite16(value, core->bus->mmio + offset); 578369ae33SRafał Miłecki } 588369ae33SRafał Miłecki 598369ae33SRafał Miłecki static void bcma_host_pci_write32(struct bcma_device *core, u16 offset, 608369ae33SRafał Miłecki u32 value) 618369ae33SRafał Miłecki { 628369ae33SRafał Miłecki if (core->bus->mapped_core != core) 638369ae33SRafał Miłecki bcma_host_pci_switch_core(core); 648369ae33SRafał Miłecki iowrite32(value, core->bus->mmio + offset); 658369ae33SRafał Miłecki } 668369ae33SRafał Miłecki 678369ae33SRafał Miłecki static u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset) 688369ae33SRafał Miłecki { 698369ae33SRafał Miłecki if (core->bus->mapped_core != core) 708369ae33SRafał Miłecki bcma_host_pci_switch_core(core); 718369ae33SRafał Miłecki return ioread32(core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset); 728369ae33SRafał Miłecki } 738369ae33SRafał Miłecki 748369ae33SRafał Miłecki static void bcma_host_pci_awrite32(struct bcma_device *core, u16 offset, 758369ae33SRafał Miłecki u32 value) 768369ae33SRafał Miłecki { 778369ae33SRafał Miłecki if (core->bus->mapped_core != core) 788369ae33SRafał Miłecki bcma_host_pci_switch_core(core); 798369ae33SRafał Miłecki iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset); 808369ae33SRafał Miłecki } 818369ae33SRafał Miłecki 828369ae33SRafał Miłecki const struct bcma_host_ops bcma_host_pci_ops = { 838369ae33SRafał Miłecki .read8 = bcma_host_pci_read8, 848369ae33SRafał Miłecki .read16 = bcma_host_pci_read16, 858369ae33SRafał Miłecki .read32 = bcma_host_pci_read32, 868369ae33SRafał Miłecki .write8 = bcma_host_pci_write8, 878369ae33SRafał Miłecki .write16 = bcma_host_pci_write16, 888369ae33SRafał Miłecki .write32 = bcma_host_pci_write32, 898369ae33SRafał Miłecki .aread32 = bcma_host_pci_aread32, 908369ae33SRafał Miłecki .awrite32 = bcma_host_pci_awrite32, 918369ae33SRafał Miłecki }; 928369ae33SRafał Miłecki 938369ae33SRafał Miłecki static int bcma_host_pci_probe(struct pci_dev *dev, 948369ae33SRafał Miłecki const struct pci_device_id *id) 958369ae33SRafał Miłecki { 968369ae33SRafał Miłecki struct bcma_bus *bus; 978369ae33SRafał Miłecki int err = -ENOMEM; 988369ae33SRafał Miłecki const char *name; 998369ae33SRafał Miłecki u32 val; 1008369ae33SRafał Miłecki 1018369ae33SRafał Miłecki /* Alloc */ 1028369ae33SRafał Miłecki bus = kzalloc(sizeof(*bus), GFP_KERNEL); 1038369ae33SRafał Miłecki if (!bus) 1048369ae33SRafał Miłecki goto out; 1058369ae33SRafał Miłecki 1068369ae33SRafał Miłecki /* Basic PCI configuration */ 1078369ae33SRafał Miłecki err = pci_enable_device(dev); 1088369ae33SRafał Miłecki if (err) 1098369ae33SRafał Miłecki goto err_kfree_bus; 1108369ae33SRafał Miłecki 1118369ae33SRafał Miłecki name = dev_name(&dev->dev); 1128369ae33SRafał Miłecki if (dev->driver && dev->driver->name) 1138369ae33SRafał Miłecki name = dev->driver->name; 1148369ae33SRafał Miłecki err = pci_request_regions(dev, name); 1158369ae33SRafał Miłecki if (err) 1168369ae33SRafał Miłecki goto err_pci_disable; 1178369ae33SRafał Miłecki pci_set_master(dev); 1188369ae33SRafał Miłecki 1198369ae33SRafał Miłecki /* Disable the RETRY_TIMEOUT register (0x41) to keep 1208369ae33SRafał Miłecki * PCI Tx retries from interfering with C3 CPU state */ 1218369ae33SRafał Miłecki pci_read_config_dword(dev, 0x40, &val); 1228369ae33SRafał Miłecki if ((val & 0x0000ff00) != 0) 1238369ae33SRafał Miłecki pci_write_config_dword(dev, 0x40, val & 0xffff00ff); 1248369ae33SRafał Miłecki 1258369ae33SRafał Miłecki /* SSB needed additional powering up, do we have any AMBA PCI cards? */ 1268369ae33SRafał Miłecki if (!pci_is_pcie(dev)) 1278369ae33SRafał Miłecki pr_err("PCI card detected, report problems.\n"); 1288369ae33SRafał Miłecki 1298369ae33SRafał Miłecki /* Map MMIO */ 1308369ae33SRafał Miłecki err = -ENOMEM; 1318369ae33SRafał Miłecki bus->mmio = pci_iomap(dev, 0, ~0UL); 1328369ae33SRafał Miłecki if (!bus->mmio) 1338369ae33SRafał Miłecki goto err_pci_release_regions; 1348369ae33SRafał Miłecki 1358369ae33SRafał Miłecki /* Host specific */ 1368369ae33SRafał Miłecki bus->host_pci = dev; 1378369ae33SRafał Miłecki bus->hosttype = BCMA_HOSTTYPE_PCI; 1388369ae33SRafał Miłecki bus->ops = &bcma_host_pci_ops; 1398369ae33SRafał Miłecki 1408369ae33SRafał Miłecki /* Register */ 1418369ae33SRafał Miłecki err = bcma_bus_register(bus); 1428369ae33SRafał Miłecki if (err) 1438369ae33SRafał Miłecki goto err_pci_unmap_mmio; 1448369ae33SRafał Miłecki 1458369ae33SRafał Miłecki pci_set_drvdata(dev, bus); 1468369ae33SRafał Miłecki 1478369ae33SRafał Miłecki out: 1488369ae33SRafał Miłecki return err; 1498369ae33SRafał Miłecki 1508369ae33SRafał Miłecki err_pci_unmap_mmio: 1518369ae33SRafał Miłecki pci_iounmap(dev, bus->mmio); 1528369ae33SRafał Miłecki err_pci_release_regions: 1538369ae33SRafał Miłecki pci_release_regions(dev); 1548369ae33SRafał Miłecki err_pci_disable: 1558369ae33SRafał Miłecki pci_disable_device(dev); 1568369ae33SRafał Miłecki err_kfree_bus: 1578369ae33SRafał Miłecki kfree(bus); 1588369ae33SRafał Miłecki return err; 1598369ae33SRafał Miłecki } 1608369ae33SRafał Miłecki 1618369ae33SRafał Miłecki static void bcma_host_pci_remove(struct pci_dev *dev) 1628369ae33SRafał Miłecki { 1638369ae33SRafał Miłecki struct bcma_bus *bus = pci_get_drvdata(dev); 1648369ae33SRafał Miłecki 1658369ae33SRafał Miłecki bcma_bus_unregister(bus); 1668369ae33SRafał Miłecki pci_iounmap(dev, bus->mmio); 1678369ae33SRafał Miłecki pci_release_regions(dev); 1688369ae33SRafał Miłecki pci_disable_device(dev); 1698369ae33SRafał Miłecki kfree(bus); 1708369ae33SRafał Miłecki pci_set_drvdata(dev, NULL); 1718369ae33SRafał Miłecki } 1728369ae33SRafał Miłecki 1738369ae33SRafał Miłecki static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { 174*9594b56dSRafał Miłecki { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, 1758369ae33SRafał Miłecki { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, 1768369ae33SRafał Miłecki { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, 1778369ae33SRafał Miłecki { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, 1788369ae33SRafał Miłecki { 0, }, 1798369ae33SRafał Miłecki }; 1808369ae33SRafał Miłecki MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl); 1818369ae33SRafał Miłecki 1828369ae33SRafał Miłecki static struct pci_driver bcma_pci_bridge_driver = { 1838369ae33SRafał Miłecki .name = "bcma-pci-bridge", 1848369ae33SRafał Miłecki .id_table = bcma_pci_bridge_tbl, 1858369ae33SRafał Miłecki .probe = bcma_host_pci_probe, 1868369ae33SRafał Miłecki .remove = bcma_host_pci_remove, 1878369ae33SRafał Miłecki }; 1888369ae33SRafał Miłecki 1898369ae33SRafał Miłecki int __init bcma_host_pci_init(void) 1908369ae33SRafał Miłecki { 1918369ae33SRafał Miłecki return pci_register_driver(&bcma_pci_bridge_driver); 1928369ae33SRafał Miłecki } 1938369ae33SRafał Miłecki 1948369ae33SRafał Miłecki void __exit bcma_host_pci_exit(void) 1958369ae33SRafał Miłecki { 1968369ae33SRafał Miłecki pci_unregister_driver(&bcma_pci_bridge_driver); 1978369ae33SRafał Miłecki } 198