xref: /linux/drivers/bcma/host_pci.c (revision 9594b56dbed8cecc4694ed2ab7cf36c66623910e)
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