host_pci.c revision 28e7d218da975f6ae1751e293aed938952c55c98
18369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki/*
28369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki * Broadcom specific AMBA
38369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki * PCI Host
48369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki *
58369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki * Licensed under the GNU/GPL. See COPYING for details.
68369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki */
78369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
88369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki#include "bcma_private.h"
9ba7328b2d83090c2440b8d0baa6ccfc2ddf1bda6Andrew Morton#include <linux/slab.h>
108369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki#include <linux/bcma/bcma.h>
118369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki#include <linux/pci.h>
12200351c77d6aa7fc36d3a49132c68e95ad9654c8Paul Gortmaker#include <linux/module.h>
138369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
148369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckistatic void bcma_host_pci_switch_core(struct bcma_device *core)
158369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{
168369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN,
178369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki			       core->addr);
188369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2,
198369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki			       core->wrap);
208369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	core->bus->mapped_core = core;
218369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	pr_debug("Switched to core: 0x%X\n", core->id.id);
228369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki}
238369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
24439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki/* Provides access to the requested core. Returns base offset that has to be
25439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki * used. It makes use of fixed windows when possible. */
26439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłeckistatic u16 bcma_host_pci_provide_access_to_core(struct bcma_device *core)
278369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{
28439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki	switch (core->id.id) {
29439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki	case BCMA_CORE_CHIPCOMMON:
30439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki		return 3 * BCMA_CORE_SIZE;
31439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki	case BCMA_CORE_PCIE:
32439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki		return 2 * BCMA_CORE_SIZE;
33439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki	}
34439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki
358369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	if (core->bus->mapped_core != core)
368369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki		bcma_host_pci_switch_core(core);
37439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki	return 0;
38439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki}
39439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki
40439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłeckistatic u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset)
41439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki{
42439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki	offset += bcma_host_pci_provide_access_to_core(core);
438369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	return ioread8(core->bus->mmio + offset);
448369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki}
458369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
468369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckistatic u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset)
478369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{
48439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki	offset += bcma_host_pci_provide_access_to_core(core);
498369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	return ioread16(core->bus->mmio + offset);
508369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki}
518369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
528369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckistatic u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset)
538369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{
54439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki	offset += bcma_host_pci_provide_access_to_core(core);
558369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	return ioread32(core->bus->mmio + offset);
568369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki}
578369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
588369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckistatic void bcma_host_pci_write8(struct bcma_device *core, u16 offset,
598369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki				 u8 value)
608369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{
61439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki	offset += bcma_host_pci_provide_access_to_core(core);
628369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	iowrite8(value, core->bus->mmio + offset);
638369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki}
648369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
658369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckistatic void bcma_host_pci_write16(struct bcma_device *core, u16 offset,
668369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki				 u16 value)
678369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{
68439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki	offset += bcma_host_pci_provide_access_to_core(core);
698369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	iowrite16(value, core->bus->mmio + offset);
708369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki}
718369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
728369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckistatic void bcma_host_pci_write32(struct bcma_device *core, u16 offset,
738369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki				 u32 value)
748369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{
75439678f8b0fca7aeca06c6581e3679eef618721aRafał Miłecki	offset += bcma_host_pci_provide_access_to_core(core);
768369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	iowrite32(value, core->bus->mmio + offset);
778369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki}
788369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
799d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki#ifdef CONFIG_BCMA_BLOCKIO
809d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłeckivoid bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
819d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki			      size_t count, u16 offset, u8 reg_width)
829d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki{
839d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki	void __iomem *addr = core->bus->mmio + offset;
849d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki	if (core->bus->mapped_core != core)
859d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		bcma_host_pci_switch_core(core);
869d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki	switch (reg_width) {
879d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki	case sizeof(u8):
889d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		ioread8_rep(addr, buffer, count);
899d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		break;
909d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki	case sizeof(u16):
919d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		WARN_ON(count & 1);
929d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		ioread16_rep(addr, buffer, count >> 1);
939d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		break;
949d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki	case sizeof(u32):
959d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		WARN_ON(count & 3);
969d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		ioread32_rep(addr, buffer, count >> 2);
979d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		break;
989d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki	default:
999d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		WARN_ON(1);
1009d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki	}
1019d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki}
1029d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki
1039d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłeckivoid bcma_host_pci_block_write(struct bcma_device *core, const void *buffer,
1049d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki			       size_t count, u16 offset, u8 reg_width)
1059d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki{
1069d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki	void __iomem *addr = core->bus->mmio + offset;
1079d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki	if (core->bus->mapped_core != core)
1089d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		bcma_host_pci_switch_core(core);
1099d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki	switch (reg_width) {
1109d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki	case sizeof(u8):
1119d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		iowrite8_rep(addr, buffer, count);
1129d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		break;
1139d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki	case sizeof(u16):
1149d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		WARN_ON(count & 1);
1159d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		iowrite16_rep(addr, buffer, count >> 1);
1169d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		break;
1179d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki	case sizeof(u32):
1189d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		WARN_ON(count & 3);
1199d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		iowrite32_rep(addr, buffer, count >> 2);
1209d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		break;
1219d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki	default:
1229d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki		WARN_ON(1);
1239d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki	}
1249d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki}
1259d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki#endif
1269d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki
1278369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckistatic u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset)
1288369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{
1298369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	if (core->bus->mapped_core != core)
1308369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki		bcma_host_pci_switch_core(core);
1318369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	return ioread32(core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset);
1328369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki}
1338369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
1348369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckistatic void bcma_host_pci_awrite32(struct bcma_device *core, u16 offset,
1358369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki				  u32 value)
1368369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{
1378369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	if (core->bus->mapped_core != core)
1388369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki		bcma_host_pci_switch_core(core);
1398369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset);
1408369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki}
1418369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
1428369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckiconst struct bcma_host_ops bcma_host_pci_ops = {
1438369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	.read8		= bcma_host_pci_read8,
1448369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	.read16		= bcma_host_pci_read16,
1458369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	.read32		= bcma_host_pci_read32,
1468369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	.write8		= bcma_host_pci_write8,
1478369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	.write16	= bcma_host_pci_write16,
1488369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	.write32	= bcma_host_pci_write32,
1499d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki#ifdef CONFIG_BCMA_BLOCKIO
1509d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki	.block_read	= bcma_host_pci_block_read,
1519d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki	.block_write	= bcma_host_pci_block_write,
1529d75ef0f8f6d2e31ed940b3057a42a25f07076fbRafał Miłecki#endif
1538369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	.aread32	= bcma_host_pci_aread32,
1548369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	.awrite32	= bcma_host_pci_awrite32,
1558369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki};
1568369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
1578369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckistatic int bcma_host_pci_probe(struct pci_dev *dev,
1588369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki			     const struct pci_device_id *id)
1598369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{
1608369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	struct bcma_bus *bus;
1618369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	int err = -ENOMEM;
1628369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	const char *name;
1638369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	u32 val;
1648369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
1658369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	/* Alloc */
1668369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	bus = kzalloc(sizeof(*bus), GFP_KERNEL);
1678369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	if (!bus)
1688369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki		goto out;
1698369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
1708369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	/* Basic PCI configuration */
1718369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	err = pci_enable_device(dev);
1728369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	if (err)
1738369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki		goto err_kfree_bus;
1748369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
1758369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	name = dev_name(&dev->dev);
1768369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	if (dev->driver && dev->driver->name)
1778369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki		name = dev->driver->name;
1788369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	err = pci_request_regions(dev, name);
1798369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	if (err)
1808369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki		goto err_pci_disable;
1818369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	pci_set_master(dev);
1828369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
1838369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	/* Disable the RETRY_TIMEOUT register (0x41) to keep
1848369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	 * PCI Tx retries from interfering with C3 CPU state */
1858369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	pci_read_config_dword(dev, 0x40, &val);
1868369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	if ((val & 0x0000ff00) != 0)
1878369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki		pci_write_config_dword(dev, 0x40, val & 0xffff00ff);
1888369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
1898369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	/* SSB needed additional powering up, do we have any AMBA PCI cards? */
1908369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	if (!pci_is_pcie(dev))
1918369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki		pr_err("PCI card detected, report problems.\n");
1928369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
1938369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	/* Map MMIO */
1948369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	err = -ENOMEM;
1958369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	bus->mmio = pci_iomap(dev, 0, ~0UL);
1968369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	if (!bus->mmio)
1978369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki		goto err_pci_release_regions;
1988369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
1998369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	/* Host specific */
2008369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	bus->host_pci = dev;
2018369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	bus->hosttype = BCMA_HOSTTYPE_PCI;
2028369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	bus->ops = &bcma_host_pci_ops;
2038369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
2048369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	/* Register */
2058369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	err = bcma_bus_register(bus);
2068369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	if (err)
2078369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki		goto err_pci_unmap_mmio;
2088369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
2098369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	pci_set_drvdata(dev, bus);
2108369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
2118369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckiout:
2128369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	return err;
2138369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
2148369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckierr_pci_unmap_mmio:
2158369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	pci_iounmap(dev, bus->mmio);
2168369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckierr_pci_release_regions:
2178369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	pci_release_regions(dev);
2188369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckierr_pci_disable:
2198369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	pci_disable_device(dev);
2208369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckierr_kfree_bus:
2218369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	kfree(bus);
2228369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	return err;
2238369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki}
2248369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
2258369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckistatic void bcma_host_pci_remove(struct pci_dev *dev)
2268369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{
2278369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	struct bcma_bus *bus = pci_get_drvdata(dev);
2288369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
2298369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	bcma_bus_unregister(bus);
2308369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	pci_iounmap(dev, bus->mmio);
2318369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	pci_release_regions(dev);
2328369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	pci_disable_device(dev);
2338369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	kfree(bus);
2348369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	pci_set_drvdata(dev, NULL);
2358369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki}
2368369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
237775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki#ifdef CONFIG_PM
238775ab52142b02237a54184238e922251c59a2b5cRafał Miłeckistatic int bcma_host_pci_suspend(struct pci_dev *dev, pm_message_t state)
239775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki{
24028e7d218da975f6ae1751e293aed938952c55c98Rafał Miłecki	struct bcma_bus *bus = pci_get_drvdata(dev);
24128e7d218da975f6ae1751e293aed938952c55c98Rafał Miłecki
242775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki	/* Host specific */
243775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki	pci_save_state(dev);
244775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki	pci_disable_device(dev);
245775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki	pci_set_power_state(dev, pci_choose_state(dev, state));
246775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki
24728e7d218da975f6ae1751e293aed938952c55c98Rafał Miłecki	bus->mapped_core = NULL;
248775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki	return 0;
249775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki}
250775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki
251775ab52142b02237a54184238e922251c59a2b5cRafał Miłeckistatic int bcma_host_pci_resume(struct pci_dev *dev)
252775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki{
253775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki	struct bcma_bus *bus = pci_get_drvdata(dev);
254775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki	int err;
255775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki
256775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki	/* Host specific */
257775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki	pci_set_power_state(dev, 0);
258775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki	err = pci_enable_device(dev);
259775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki	if (err)
260775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki		return err;
261775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki	pci_restore_state(dev);
262775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki
263775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki	/* Bus specific */
264775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki	err = bcma_bus_resume(bus);
265775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki	if (err)
266775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki		return err;
267775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki
268775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki	return 0;
269775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki}
270775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki#else /* CONFIG_PM */
271775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki# define bcma_host_pci_suspend	NULL
272775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki# define bcma_host_pci_resume	NULL
273775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki#endif /* CONFIG_PM */
274775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki
2758369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckistatic DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
2769594b56dbed8cecc4694ed2ab7cf36c66623910eRafał Miłecki	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
2778369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
2788369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
27991fa4b0a6b92ebef3d5e26b709faf62a3b44beb0Rafał Miłecki	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
2808369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
2818369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	{ 0, },
2828369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki};
2838369ae33b705222aa05ab53c7d6b4458f4ed161bRafał MiłeckiMODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl);
2848369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
2858369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckistatic struct pci_driver bcma_pci_bridge_driver = {
2868369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	.name = "bcma-pci-bridge",
2878369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	.id_table = bcma_pci_bridge_tbl,
2888369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	.probe = bcma_host_pci_probe,
2898369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	.remove = bcma_host_pci_remove,
290775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki	.suspend = bcma_host_pci_suspend,
291775ab52142b02237a54184238e922251c59a2b5cRafał Miłecki	.resume = bcma_host_pci_resume,
2928369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki};
2938369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
2948369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckiint __init bcma_host_pci_init(void)
2958369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{
2968369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	return pci_register_driver(&bcma_pci_bridge_driver);
2978369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki}
2988369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki
2998369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłeckivoid __exit bcma_host_pci_exit(void)
3008369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki{
3018369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki	pci_unregister_driver(&bcma_pci_bridge_driver);
3028369ae33b705222aa05ab53c7d6b4458f4ed161bRafał Miłecki}
303