From 273797f15a2ec0fc47cd88a92904a5712bd6539e Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Thu, 17 May 2012 13:22:38 +0000
Subject: [PATCH] kernel: ssb/bcma: update to version from wireless-testing tag
 master-2012-05-16-2

SVN-Revision: 31772
---
 .../mac80211/patches/840-b43-backport.patch   |  159 +
 .../patches-3.3/047-bcma-add-new-PCI-ID.patch |    2 +-
 ...k-sprom-if-no-on-chip-sprom-is-avail.patch |   24 -
 ...82-bcma-scan-for-extra-address-space.patch |    6 +-
 .../230-bcma-find-name-for-non-brcm.patch     |   99 -
 ...bcma_account_for_variable_pci_memory.patch |   14 -
 .../234-bcma-always-map-4-bytes.patch         |   29 -
 .../238-bcma-host_pci_devexit.patch           |   20 -
 ...39-bcma-add-flush-for-resetctl-write.patch |   10 -
 .../250-ssb-remove-rev-from-boardinfo.patch   |   11 +
 ...bcm47xx-refactor-fetching-board-data.patch |   46 +
 .../252-bcma-add-boardinfo-struct.patch       |   41 +
 ...d-baordrev-without-prefix-from-sprom.patch |   11 +
 .../patches-3.3/400-arch-bcm47xx.patch        |    2 +-
 .../980-wnr834b_no_cardbus_invariant.patch    |    2 +-
 .../patches-2.6.39/020-ssb_update.patch       |  519 +-
 .../patches-2.6.39/021-ssb_add_pci_id.patch   |   11 -
 .../patches-2.6.39/025-bcma_backport.patch    | 6768 +++++++++--------
 .../generic/patches-3.1/020-ssb_update.patch  |  282 +-
 .../patches-3.1/021-ssb_add_pci_id.patch      |   11 -
 .../patches-3.1/025-bcma_backport.patch       |  443 +-
 .../generic/patches-3.2/020-ssb_update.patch  |  289 +-
 .../patches-3.2/021-ssb_add_pci_id.patch      |   11 -
 .../patches-3.2/025-bcma_backport.patch       | 1132 ++-
 .../generic/patches-3.3/020-ssb_update.patch  |  279 +-
 .../patches-3.3/021-ssb_add_pci_id.patch      |   11 -
 .../patches-3.3/025-bcma_backport.patch       |  441 +-
 27 files changed, 6509 insertions(+), 4164 deletions(-)
 create mode 100644 package/mac80211/patches/840-b43-backport.patch
 delete mode 100644 target/linux/brcm47xx/patches-3.3/060-bcma-use-fallback-sprom-if-no-on-chip-sprom-is-avail.patch
 delete mode 100644 target/linux/brcm47xx/patches-3.3/230-bcma-find-name-for-non-brcm.patch
 delete mode 100644 target/linux/brcm47xx/patches-3.3/232-bcma_account_for_variable_pci_memory.patch
 delete mode 100644 target/linux/brcm47xx/patches-3.3/234-bcma-always-map-4-bytes.patch
 delete mode 100644 target/linux/brcm47xx/patches-3.3/238-bcma-host_pci_devexit.patch
 delete mode 100644 target/linux/brcm47xx/patches-3.3/239-bcma-add-flush-for-resetctl-write.patch
 create mode 100644 target/linux/brcm47xx/patches-3.3/250-ssb-remove-rev-from-boardinfo.patch
 create mode 100644 target/linux/brcm47xx/patches-3.3/251-MIPS-bcm47xx-refactor-fetching-board-data.patch
 create mode 100644 target/linux/brcm47xx/patches-3.3/252-bcma-add-boardinfo-struct.patch
 create mode 100644 target/linux/brcm47xx/patches-3.3/253-MIPS-bcm47xx-read-baordrev-without-prefix-from-sprom.patch
 delete mode 100644 target/linux/generic/patches-2.6.39/021-ssb_add_pci_id.patch
 delete mode 100644 target/linux/generic/patches-3.1/021-ssb_add_pci_id.patch
 delete mode 100644 target/linux/generic/patches-3.2/021-ssb_add_pci_id.patch
 delete mode 100644 target/linux/generic/patches-3.3/021-ssb_add_pci_id.patch

diff --git a/package/mac80211/patches/840-b43-backport.patch b/package/mac80211/patches/840-b43-backport.patch
new file mode 100644
index 0000000000..b2bb22a665
--- /dev/null
+++ b/package/mac80211/patches/840-b43-backport.patch
@@ -0,0 +1,159 @@
+--- a/drivers/net/wireless/b43/bus.c
++++ b/drivers/net/wireless/b43/bus.c
+@@ -107,11 +107,9 @@ struct b43_bus_dev *b43_bus_dev_bcma_ini
+ 	dev->dma_dev = core->dma_dev;
+ 	dev->irq = core->irq;
+ 
+-	/*
+ 	dev->board_vendor = core->bus->boardinfo.vendor;
+ 	dev->board_type = core->bus->boardinfo.type;
+-	dev->board_rev = core->bus->boardinfo.rev;
+-	*/
++	dev->board_rev = core->bus->sprom.board_rev;
+ 
+ 	dev->chip_id = core->bus->chipinfo.id;
+ 	dev->chip_rev = core->bus->chipinfo.rev;
+@@ -210,7 +208,7 @@ struct b43_bus_dev *b43_bus_dev_ssb_init
+ 
+ 	dev->board_vendor = sdev->bus->boardinfo.vendor;
+ 	dev->board_type = sdev->bus->boardinfo.type;
+-	dev->board_rev = sdev->bus->boardinfo.rev;
++	dev->board_rev = sdev->bus->sprom.board_rev;
+ 
+ 	dev->chip_id = sdev->bus->chip_id;
+ 	dev->chip_rev = sdev->bus->chip_rev;
+--- a/drivers/net/wireless/b43/dma.c
++++ b/drivers/net/wireless/b43/dma.c
+@@ -1109,7 +1109,7 @@ static bool b43_dma_translation_in_low_w
+ #ifdef CONFIG_B43_SSB
+ 	if (dev->dev->bus_type == B43_BUS_SSB &&
+ 	    dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
+-	    !(dev->dev->sdev->bus->host_pci->is_pcie &&
++	    !(pci_is_pcie(dev->dev->sdev->bus->host_pci) &&
+ 	      ssb_read32(dev->dev->sdev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64))
+ 			return 1;
+ #endif
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -4834,8 +4834,14 @@ static int b43_op_start(struct ieee80211
+  out_mutex_unlock:
+ 	mutex_unlock(&wl->mutex);
+ 
+-	/* reload configuration */
+-	b43_op_config(hw, ~0);
++	/*
++	 * Configuration may have been overwritten during initialization.
++	 * Reload the configuration, but only if initialization was
++	 * successful. Reloading the configuration after a failed init
++	 * may hang the system.
++	 */
++	if (!err)
++		b43_op_config(hw, ~0);
+ 
+ 	return err;
+ }
+@@ -5279,10 +5285,10 @@ static void b43_sprom_fixup(struct ssb_b
+ 
+ 	/* boardflags workarounds */
+ 	if (bus->boardinfo.vendor == SSB_BOARDVENDOR_DELL &&
+-	    bus->chip_id == 0x4301 && bus->boardinfo.rev == 0x74)
++	    bus->chip_id == 0x4301 && bus->sprom.board_rev == 0x74)
+ 		bus->sprom.boardflags_lo |= B43_BFL_BTCOEXIST;
+ 	if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
+-	    bus->boardinfo.type == 0x4E && bus->boardinfo.rev > 0x40)
++	    bus->boardinfo.type == 0x4E && bus->sprom.board_rev > 0x40)
+ 		bus->sprom.boardflags_lo |= B43_BFL_PACTRL;
+ 	if (bus->bustype == SSB_BUSTYPE_PCI) {
+ 		pdev = bus->host_pci;
+--- a/drivers/net/wireless/b43/sdio.c
++++ b/drivers/net/wireless/b43/sdio.c
+@@ -193,7 +193,7 @@ static struct sdio_driver b43_sdio_drive
+ 	.name		= "b43-sdio",
+ 	.id_table	= b43_sdio_ids,
+ 	.probe		= b43_sdio_probe,
+-	.remove		= b43_sdio_remove,
++	.remove		= __devexit_p(b43_sdio_remove),
+ };
+ 
+ int b43_sdio_init(void)
+--- a/drivers/net/wireless/b43legacy/main.c
++++ b/drivers/net/wireless/b43legacy/main.c
+@@ -1550,8 +1550,6 @@ static void b43legacy_request_firmware(s
+ 	const char *filename;
+ 	int err;
+ 
+-	/* do dummy read */
+-	ssb_read32(dev->dev, SSB_TMSHIGH);
+ 	if (!fw->ucode) {
+ 		if (rev == 2)
+ 			filename = "ucode2";
+@@ -3758,7 +3756,7 @@ static void b43legacy_sprom_fixup(struct
+ 	/* boardflags workarounds */
+ 	if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
+ 	    bus->boardinfo.type == 0x4E &&
+-	    bus->boardinfo.rev > 0x40)
++	    bus->sprom.board_rev > 0x40)
+ 		bus->sprom.boardflags_lo |= B43legacy_BFL_PACTRL;
+ }
+ 
+--- a/drivers/net/wireless/b43legacy/phy.c
++++ b/drivers/net/wireless/b43legacy/phy.c
+@@ -408,7 +408,7 @@ static void b43legacy_phy_setupg(struct
+ 
+ 		if (is_bcm_board_vendor(dev) &&
+ 		    (dev->dev->bus->boardinfo.type == 0x0416) &&
+-		    (dev->dev->bus->boardinfo.rev == 0x0017))
++		    (dev->dev->bus->sprom.board_rev == 0x0017))
+ 			return;
+ 
+ 		b43legacy_ilt_write(dev, 0x5001, 0x0002);
+@@ -424,7 +424,7 @@ static void b43legacy_phy_setupg(struct
+ 
+ 		if (is_bcm_board_vendor(dev) &&
+ 		    (dev->dev->bus->boardinfo.type == 0x0416) &&
+-		    (dev->dev->bus->boardinfo.rev == 0x0017))
++		    (dev->dev->bus->sprom.board_rev == 0x0017))
+ 			return;
+ 
+ 		b43legacy_ilt_write(dev, 0x0401, 0x0002);
+--- a/drivers/net/wireless/b43legacy/radio.c
++++ b/drivers/net/wireless/b43legacy/radio.c
+@@ -1998,7 +1998,7 @@ u16 b43legacy_default_radio_attenuation(
+ 			if (phy->type == B43legacy_PHYTYPE_G) {
+ 				if (is_bcm_board_vendor(dev) &&
+ 				    dev->dev->bus->boardinfo.type == 0x421 &&
+-				    dev->dev->bus->boardinfo.rev >= 30)
++				    dev->dev->bus->sprom.board_rev >= 30)
+ 					att = 3;
+ 				else if (is_bcm_board_vendor(dev) &&
+ 					 dev->dev->bus->boardinfo.type == 0x416)
+@@ -2008,7 +2008,7 @@ u16 b43legacy_default_radio_attenuation(
+ 			} else {
+ 				if (is_bcm_board_vendor(dev) &&
+ 				    dev->dev->bus->boardinfo.type == 0x421 &&
+-				    dev->dev->bus->boardinfo.rev >= 30)
++				    dev->dev->bus->sprom.board_rev >= 30)
+ 					att = 7;
+ 				else
+ 					att = 6;
+@@ -2018,7 +2018,7 @@ u16 b43legacy_default_radio_attenuation(
+ 			if (phy->type == B43legacy_PHYTYPE_G) {
+ 				if (is_bcm_board_vendor(dev) &&
+ 				    dev->dev->bus->boardinfo.type == 0x421 &&
+-				    dev->dev->bus->boardinfo.rev >= 30)
++				    dev->dev->bus->sprom.board_rev >= 30)
+ 					att = 3;
+ 				else if (is_bcm_board_vendor(dev) &&
+ 					 dev->dev->bus->boardinfo.type ==
+@@ -2052,9 +2052,9 @@ u16 b43legacy_default_radio_attenuation(
+ 	}
+ 	if (is_bcm_board_vendor(dev) &&
+ 	    dev->dev->bus->boardinfo.type == 0x421) {
+-		if (dev->dev->bus->boardinfo.rev < 0x43)
++		if (dev->dev->bus->sprom.board_rev < 0x43)
+ 			att = 2;
+-		else if (dev->dev->bus->boardinfo.rev < 0x51)
++		else if (dev->dev->bus->sprom.board_rev < 0x51)
+ 			att = 3;
+ 	}
+ 	if (att == 0xFFFF)
diff --git a/target/linux/brcm47xx/patches-3.3/047-bcma-add-new-PCI-ID.patch b/target/linux/brcm47xx/patches-3.3/047-bcma-add-new-PCI-ID.patch
index 77062c3dab..fb658345e6 100644
--- a/target/linux/brcm47xx/patches-3.3/047-bcma-add-new-PCI-ID.patch
+++ b/target/linux/brcm47xx/patches-3.3/047-bcma-add-new-PCI-ID.patch
@@ -14,7 +14,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 
 --- a/drivers/bcma/host_pci.c
 +++ b/drivers/bcma/host_pci.c
-@@ -269,6 +269,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_
+@@ -272,6 +272,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_
  	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
  	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
  	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
diff --git a/target/linux/brcm47xx/patches-3.3/060-bcma-use-fallback-sprom-if-no-on-chip-sprom-is-avail.patch b/target/linux/brcm47xx/patches-3.3/060-bcma-use-fallback-sprom-if-no-on-chip-sprom-is-avail.patch
deleted file mode 100644
index abc638d244..0000000000
--- a/target/linux/brcm47xx/patches-3.3/060-bcma-use-fallback-sprom-if-no-on-chip-sprom-is-avail.patch
+++ /dev/null
@@ -1,24 +0,0 @@
---- a/drivers/bcma/sprom.c
-+++ b/drivers/bcma/sprom.c
-@@ -404,16 +404,19 @@ int bcma_sprom_get(struct bcma_bus *bus)
- 		return -EOPNOTSUPP;
- 
- 	if (!bcma_sprom_ext_available(bus)) {
-+		bool sprom_onchip;
-+
- 		/*
- 		 * External SPROM takes precedence so check
- 		 * on-chip OTP only when no external SPROM
- 		 * is present.
- 		 */
--		if (bcma_sprom_onchip_available(bus)) {
-+		sprom_onchip = bcma_sprom_onchip_available(bus);
-+		if (sprom_onchip) {
- 			/* determine offset */
- 			offset = bcma_sprom_onchip_offset(bus);
- 		}
--		if (!offset) {
-+		if (!offset || !sprom_onchip) {
- 			/*
- 			 * Maybe there is no SPROM on the device?
- 			 * Now we ask the arch code if there is some sprom
diff --git a/target/linux/brcm47xx/patches-3.3/182-bcma-scan-for-extra-address-space.patch b/target/linux/brcm47xx/patches-3.3/182-bcma-scan-for-extra-address-space.patch
index 6e68f0cc8f..fdf5cfbe9d 100644
--- a/target/linux/brcm47xx/patches-3.3/182-bcma-scan-for-extra-address-space.patch
+++ b/target/linux/brcm47xx/patches-3.3/182-bcma-scan-for-extra-address-space.patch
@@ -1,6 +1,6 @@
 --- a/drivers/bcma/scan.c
 +++ b/drivers/bcma/scan.c
-@@ -297,6 +297,23 @@ static int bcma_get_next_core(struct bcm
+@@ -323,6 +323,23 @@ static int bcma_get_next_core(struct bcm
  			return -EILSEQ;
  	}
  
@@ -24,7 +24,7 @@
  	/* get & parse slave ports */
  	for (i = 0; i < ports[1]; i++) {
  		for (j = 0; ; j++) {
-@@ -309,7 +326,7 @@ static int bcma_get_next_core(struct bcm
+@@ -335,7 +352,7 @@ static int bcma_get_next_core(struct bcm
  				break;
  			} else {
  				if (i == 0 && j == 0)
@@ -35,7 +35,7 @@
  	}
 --- a/include/linux/bcma/bcma.h
 +++ b/include/linux/bcma/bcma.h
-@@ -139,6 +139,7 @@ struct bcma_device {
+@@ -144,6 +144,7 @@ struct bcma_device {
  	u8 core_unit;
  
  	u32 addr;
diff --git a/target/linux/brcm47xx/patches-3.3/230-bcma-find-name-for-non-brcm.patch b/target/linux/brcm47xx/patches-3.3/230-bcma-find-name-for-non-brcm.patch
deleted file mode 100644
index 54addee966..0000000000
--- a/target/linux/brcm47xx/patches-3.3/230-bcma-find-name-for-non-brcm.patch
+++ /dev/null
@@ -1,99 +0,0 @@
---- a/drivers/bcma/scan.c
-+++ b/drivers/bcma/scan.c
-@@ -19,7 +19,14 @@ struct bcma_device_id_name {
- 	u16 id;
- 	const char *name;
- };
--struct bcma_device_id_name bcma_device_names[] = {
-+
-+static const struct bcma_device_id_name bcma_arm_device_names[] = {
-+	{ BCMA_CORE_ARM_1176, "ARM 1176" },
-+	{ BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },
-+	{ BCMA_CORE_ARM_CM3, "ARM CM3" },
-+};
-+
-+static const struct bcma_device_id_name bcma_bcm_device_names[] = {
- 	{ BCMA_CORE_OOB_ROUTER, "OOB Router" },
- 	{ BCMA_CORE_INVALID, "Invalid" },
- 	{ BCMA_CORE_CHIPCOMMON, "ChipCommon" },
-@@ -27,7 +34,6 @@ struct bcma_device_id_name bcma_device_n
- 	{ BCMA_CORE_SRAM, "SRAM" },
- 	{ BCMA_CORE_SDRAM, "SDRAM" },
- 	{ BCMA_CORE_PCI, "PCI" },
--	{ BCMA_CORE_MIPS, "MIPS" },
- 	{ BCMA_CORE_ETHERNET, "Fast Ethernet" },
- 	{ BCMA_CORE_V90, "V90" },
- 	{ BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" },
-@@ -44,7 +50,6 @@ struct bcma_device_id_name bcma_device_n
- 	{ BCMA_CORE_PHY_A, "PHY A" },
- 	{ BCMA_CORE_PHY_B, "PHY B" },
- 	{ BCMA_CORE_PHY_G, "PHY G" },
--	{ BCMA_CORE_MIPS_3302, "MIPS 3302" },
- 	{ BCMA_CORE_USB11_HOST, "USB 1.1 Host" },
- 	{ BCMA_CORE_USB11_DEV, "USB 1.1 Device" },
- 	{ BCMA_CORE_USB20_HOST, "USB 2.0 Host" },
-@@ -58,15 +63,11 @@ struct bcma_device_id_name bcma_device_n
- 	{ BCMA_CORE_PHY_N, "PHY N" },
- 	{ BCMA_CORE_SRAM_CTL, "SRAM Controller" },
- 	{ BCMA_CORE_MINI_MACPHY, "Mini MACPHY" },
--	{ BCMA_CORE_ARM_1176, "ARM 1176" },
--	{ BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },
- 	{ BCMA_CORE_PHY_LP, "PHY LP" },
- 	{ BCMA_CORE_PMU, "PMU" },
- 	{ BCMA_CORE_PHY_SSN, "PHY SSN" },
- 	{ BCMA_CORE_SDIO_DEV, "SDIO Device" },
--	{ BCMA_CORE_ARM_CM3, "ARM CM3" },
- 	{ BCMA_CORE_PHY_HT, "PHY HT" },
--	{ BCMA_CORE_MIPS_74K, "MIPS 74K" },
- 	{ BCMA_CORE_MAC_GBIT, "GBit MAC" },
- 	{ BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" },
- 	{ BCMA_CORE_PCIE_RC, "PCIe Root Complex" },
-@@ -79,16 +80,41 @@ struct bcma_device_id_name bcma_device_n
- 	{ BCMA_CORE_SHIM, "SHIM" },
- 	{ BCMA_CORE_DEFAULT, "Default" },
- };
--const char *bcma_device_name(struct bcma_device_id *id)
-+
-+static const struct bcma_device_id_name bcma_mips_device_names[] = {
-+	{ BCMA_CORE_MIPS, "MIPS" },
-+	{ BCMA_CORE_MIPS_3302, "MIPS 3302" },
-+	{ BCMA_CORE_MIPS_74K, "MIPS 74K" },
-+};
-+
-+static const char *bcma_device_name(const struct bcma_device_id *id)
- {
--	int i;
-+	const struct bcma_device_id_name *names;
-+	int size, i;
- 
--	if (id->manuf == BCMA_MANUF_BCM) {
--		for (i = 0; i < ARRAY_SIZE(bcma_device_names); i++) {
--			if (bcma_device_names[i].id == id->id)
--				return bcma_device_names[i].name;
--		}
-+	/* search manufacturer specific names */
-+	switch (id->manuf) {
-+	case BCMA_MANUF_ARM:
-+		names = bcma_arm_device_names;
-+		size = ARRAY_SIZE(bcma_arm_device_names);
-+		break;
-+	case BCMA_MANUF_BCM:
-+		names = bcma_bcm_device_names;
-+		size = ARRAY_SIZE(bcma_bcm_device_names);
-+		break;
-+	case BCMA_MANUF_MIPS:
-+		names = bcma_mips_device_names;
-+		size = ARRAY_SIZE(bcma_mips_device_names);
-+		break;
-+	default:
-+		return "UNKNOWN";
- 	}
-+
-+	for (i = 0; i < size; i++) {
-+		if (names[i].id == id->id)
-+			return names[i].name;
-+	}
-+
- 	return "UNKNOWN";
- }
- 
diff --git a/target/linux/brcm47xx/patches-3.3/232-bcma_account_for_variable_pci_memory.patch b/target/linux/brcm47xx/patches-3.3/232-bcma_account_for_variable_pci_memory.patch
deleted file mode 100644
index 3a2d512dc7..0000000000
--- a/target/linux/brcm47xx/patches-3.3/232-bcma_account_for_variable_pci_memory.patch
+++ /dev/null
@@ -1,14 +0,0 @@
---- a/drivers/bcma/driver_pci_host.c
-+++ b/drivers/bcma/driver_pci_host.c
-@@ -491,8 +491,9 @@ void __devinit bcma_core_pci_hostmode_in
- 	/* Ok, ready to run, register it to the system.
- 	 * The following needs change, if we want to port hostmode
- 	 * to non-MIPS platform. */
--	io_map_base = (unsigned long)ioremap_nocache(BCMA_SOC_PCI_MEM,
--						     0x04000000);
-+	io_map_base = (unsigned long)ioremap_nocache(pc_host->mem_resource.start,
-+						     pc_host->mem_resource.end -
-+						     pc_host->mem_resource.start + 1);
- 	pc_host->pci_controller.io_map_base = io_map_base;
- 	set_io_port_base(pc_host->pci_controller.io_map_base);
- 	/* Give some time to the PCI controller to configure itself with the new
diff --git a/target/linux/brcm47xx/patches-3.3/234-bcma-always-map-4-bytes.patch b/target/linux/brcm47xx/patches-3.3/234-bcma-always-map-4-bytes.patch
deleted file mode 100644
index adaadcc031..0000000000
--- a/target/linux/brcm47xx/patches-3.3/234-bcma-always-map-4-bytes.patch
+++ /dev/null
@@ -1,29 +0,0 @@
---- a/drivers/bcma/driver_pci_host.c
-+++ b/drivers/bcma/driver_pci_host.c
-@@ -119,7 +119,7 @@ static int bcma_extpci_read_config(struc
- 		if (unlikely(!addr))
- 			goto out;
- 		err = -ENOMEM;
--		mmio = ioremap_nocache(addr, len);
-+		mmio = ioremap_nocache(addr, sizeof(val));
- 		if (!mmio)
- 			goto out;
- 
-@@ -171,7 +171,7 @@ static int bcma_extpci_write_config(stru
- 			addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0;
- 			addr |= (func << 8);
- 			addr |= (off & 0xfc);
--			mmio = ioremap_nocache(addr, len);
-+			mmio = ioremap_nocache(addr, sizeof(val));
- 			if (!mmio)
- 				goto out;
- 		}
-@@ -180,7 +180,7 @@ static int bcma_extpci_write_config(stru
- 		if (unlikely(!addr))
- 			goto out;
- 		err = -ENOMEM;
--		mmio = ioremap_nocache(addr, len);
-+		mmio = ioremap_nocache(addr, sizeof(val));
- 		if (!mmio)
- 			goto out;
- 
diff --git a/target/linux/brcm47xx/patches-3.3/238-bcma-host_pci_devexit.patch b/target/linux/brcm47xx/patches-3.3/238-bcma-host_pci_devexit.patch
deleted file mode 100644
index 85b47fa7f8..0000000000
--- a/target/linux/brcm47xx/patches-3.3/238-bcma-host_pci_devexit.patch
+++ /dev/null
@@ -1,20 +0,0 @@
---- a/drivers/bcma/host_pci.c
-+++ b/drivers/bcma/host_pci.c
-@@ -222,7 +222,7 @@ err_kfree_bus:
- 	return err;
- }
- 
--static void bcma_host_pci_remove(struct pci_dev *dev)
-+static void __devexit bcma_host_pci_remove(struct pci_dev *dev)
- {
- 	struct bcma_bus *bus = pci_get_drvdata(dev);
- 
-@@ -278,7 +278,7 @@ static struct pci_driver bcma_pci_bridge
- 	.name = "bcma-pci-bridge",
- 	.id_table = bcma_pci_bridge_tbl,
- 	.probe = bcma_host_pci_probe,
--	.remove = bcma_host_pci_remove,
-+	.remove = __devexit_p(bcma_host_pci_remove),
- 	.driver.pm = BCMA_PM_OPS,
- };
- 
diff --git a/target/linux/brcm47xx/patches-3.3/239-bcma-add-flush-for-resetctl-write.patch b/target/linux/brcm47xx/patches-3.3/239-bcma-add-flush-for-resetctl-write.patch
deleted file mode 100644
index 285c356adf..0000000000
--- a/target/linux/brcm47xx/patches-3.3/239-bcma-add-flush-for-resetctl-write.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/drivers/bcma/core.c
-+++ b/drivers/bcma/core.c
-@@ -30,6 +30,7 @@ void bcma_core_disable(struct bcma_devic
- 	udelay(10);
- 
- 	bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
-+	bcma_aread32(core, BCMA_RESET_CTL);
- 	udelay(1);
- }
- EXPORT_SYMBOL_GPL(bcma_core_disable);
diff --git a/target/linux/brcm47xx/patches-3.3/250-ssb-remove-rev-from-boardinfo.patch b/target/linux/brcm47xx/patches-3.3/250-ssb-remove-rev-from-boardinfo.patch
new file mode 100644
index 0000000000..9e9f426605
--- /dev/null
+++ b/target/linux/brcm47xx/patches-3.3/250-ssb-remove-rev-from-boardinfo.patch
@@ -0,0 +1,11 @@
+--- a/arch/mips/bcm47xx/setup.c
++++ b/arch/mips/bcm47xx/setup.c
+@@ -163,8 +163,6 @@ static int bcm47xx_get_invariants(struct
+ 		iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
+ 	if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
+ 		iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
+-	if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
+-		iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
+ 
+ 	memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
+ 	bcm47xx_fill_sprom(&iv->sprom, NULL);
diff --git a/target/linux/brcm47xx/patches-3.3/251-MIPS-bcm47xx-refactor-fetching-board-data.patch b/target/linux/brcm47xx/patches-3.3/251-MIPS-bcm47xx-refactor-fetching-board-data.patch
new file mode 100644
index 0000000000..a50cd8c048
--- /dev/null
+++ b/target/linux/brcm47xx/patches-3.3/251-MIPS-bcm47xx-refactor-fetching-board-data.patch
@@ -0,0 +1,46 @@
+--- a/arch/mips/bcm47xx/setup.c
++++ b/arch/mips/bcm47xx/setup.c
+@@ -157,12 +157,7 @@ static int bcm47xx_get_invariants(struct
+ 	/* Fill boardinfo structure */
+ 	memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
+ 
+-	if (nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
+-		iv->boardinfo.vendor = (u16)simple_strtoul(buf, NULL, 0);
+-	else
+-		iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
+-	if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
+-		iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
++	bcm47xx_fill_ssb_boardinfo(&iv->boardinfo, NULL);
+ 
+ 	memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
+ 	bcm47xx_fill_sprom(&iv->sprom, NULL);
+--- a/arch/mips/bcm47xx/sprom.c
++++ b/arch/mips/bcm47xx/sprom.c
+@@ -616,3 +616,15 @@ void bcm47xx_fill_sprom(struct ssb_sprom
+ 		bcm47xx_fill_sprom_r1(sprom, prefix);
+ 	}
+ }
++
++#ifdef CONFIG_BCM47XX_SSB
++void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
++				const char *prefix)
++{
++	nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0);
++	if (!boardinfo->vendor)
++		boardinfo->vendor = SSB_BOARDVENDOR_BCM;
++
++	nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0);
++}
++#endif
+--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
++++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
+@@ -47,4 +47,9 @@ extern enum bcm47xx_bus_type bcm47xx_bus
+ void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix);
+ void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix);
+ 
++#ifdef CONFIG_BCM47XX_SSB
++void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
++				const char *prefix);
++#endif
++
+ #endif /* __ASM_BCM47XX_H */
diff --git a/target/linux/brcm47xx/patches-3.3/252-bcma-add-boardinfo-struct.patch b/target/linux/brcm47xx/patches-3.3/252-bcma-add-boardinfo-struct.patch
new file mode 100644
index 0000000000..31ed817cca
--- /dev/null
+++ b/target/linux/brcm47xx/patches-3.3/252-bcma-add-boardinfo-struct.patch
@@ -0,0 +1,41 @@
+--- a/arch/mips/bcm47xx/setup.c
++++ b/arch/mips/bcm47xx/setup.c
+@@ -297,6 +297,8 @@ static void __init bcm47xx_register_bcma
+ 	
+ 	if (bcm47xx_bus.bcma.bus.drv_cc.flash_type == BCMA_NFLASH)
+ 		bcm47xx_nflash_struct_bcma_init(&bcm47xx_nflash, &bcm47xx_bus.bcma.bus.drv_cc);
++
++	bcm47xx_fill_bcma_boardinfo(&bcm47xx_bus.bcma.bus.boardinfo, NULL);
+ }
+ 
+ static int __init bcm47xx_register_flash_bcma(void)
+--- a/arch/mips/bcm47xx/sprom.c
++++ b/arch/mips/bcm47xx/sprom.c
+@@ -628,3 +628,15 @@ void bcm47xx_fill_ssb_boardinfo(struct s
+ 	nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0);
+ }
+ #endif
++
++#ifdef CONFIG_BCM47XX_BCMA
++void bcm47xx_fill_bcma_boardinfo(struct bcma_boardinfo *boardinfo,
++				 const char *prefix)
++{
++	nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0);
++	if (!boardinfo->vendor)
++		boardinfo->vendor = SSB_BOARDVENDOR_BCM;
++
++	nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0);
++}
++#endif
+--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
++++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
+@@ -51,5 +51,9 @@ void bcm47xx_fill_sprom_ethernet(struct
+ void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
+ 				const char *prefix);
+ #endif
++#ifdef CONFIG_BCM47XX_BCMA
++void bcm47xx_fill_bcma_boardinfo(struct bcma_boardinfo *boardinfo,
++				 const char *prefix);
++#endif
+ 
+ #endif /* __ASM_BCM47XX_H */
diff --git a/target/linux/brcm47xx/patches-3.3/253-MIPS-bcm47xx-read-baordrev-without-prefix-from-sprom.patch b/target/linux/brcm47xx/patches-3.3/253-MIPS-bcm47xx-read-baordrev-without-prefix-from-sprom.patch
new file mode 100644
index 0000000000..108987d83d
--- /dev/null
+++ b/target/linux/brcm47xx/patches-3.3/253-MIPS-bcm47xx-read-baordrev-without-prefix-from-sprom.patch
@@ -0,0 +1,11 @@
+--- a/arch/mips/bcm47xx/sprom.c
++++ b/arch/mips/bcm47xx/sprom.c
+@@ -165,6 +165,8 @@ static void bcm47xx_fill_sprom_r1234589(
+ 					const char *prefix)
+ {
+ 	nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0);
++	if (!sprom->board_rev)
++		nvram_read_u16(NULL, NULL, "boardrev", &sprom->board_rev, 0);
+ 	nvram_read_u16(prefix, NULL, "boardnum", &sprom->board_num, 0);
+ 	nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff);
+ 	nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff);
diff --git a/target/linux/brcm47xx/patches-3.3/400-arch-bcm47xx.patch b/target/linux/brcm47xx/patches-3.3/400-arch-bcm47xx.patch
index 0933fb6959..796a98aa82 100644
--- a/target/linux/brcm47xx/patches-3.3/400-arch-bcm47xx.patch
+++ b/target/linux/brcm47xx/patches-3.3/400-arch-bcm47xx.patch
@@ -33,7 +33,7 @@
 +EXPORT_SYMBOL(nvram_get);
 --- a/arch/mips/bcm47xx/setup.c
 +++ b/arch/mips/bcm47xx/setup.c
-@@ -384,3 +384,20 @@ static int __init bcm47xx_register_flash
+@@ -379,3 +379,20 @@ static int __init bcm47xx_register_flash
  	return -1;
  }
  fs_initcall(bcm47xx_register_flash);
diff --git a/target/linux/brcm47xx/patches-3.3/980-wnr834b_no_cardbus_invariant.patch b/target/linux/brcm47xx/patches-3.3/980-wnr834b_no_cardbus_invariant.patch
index 42f00ddc31..c6de865c7e 100644
--- a/target/linux/brcm47xx/patches-3.3/980-wnr834b_no_cardbus_invariant.patch
+++ b/target/linux/brcm47xx/patches-3.3/980-wnr834b_no_cardbus_invariant.patch
@@ -1,6 +1,6 @@
 --- a/arch/mips/bcm47xx/setup.c
 +++ b/arch/mips/bcm47xx/setup.c
-@@ -172,6 +172,10 @@ static int bcm47xx_get_invariants(struct
+@@ -165,6 +165,10 @@ static int bcm47xx_get_invariants(struct
  	if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
  		iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
  
diff --git a/target/linux/generic/patches-2.6.39/020-ssb_update.patch b/target/linux/generic/patches-2.6.39/020-ssb_update.patch
index 404201a782..e6dec49b05 100644
--- a/target/linux/generic/patches-2.6.39/020-ssb_update.patch
+++ b/target/linux/generic/patches-2.6.39/020-ssb_update.patch
@@ -1,3 +1,29 @@
+--- a/drivers/ssb/b43_pci_bridge.c
++++ b/drivers/ssb/b43_pci_bridge.c
+@@ -5,12 +5,13 @@
+  * because of its small size we include it in the SSB core
+  * instead of creating a standalone module.
+  *
+- * Copyright 2007  Michael Buesch <mb@bu3sch.de>
++ * Copyright 2007  Michael Buesch <m@bues.ch>
+  *
+  * Licensed under the GNU/GPL. See COPYING for details.
+  */
+ 
+ #include <linux/pci.h>
++#include <linux/module.h>
+ #include <linux/ssb/ssb.h>
+ 
+ #include "ssb_private.h"
+@@ -28,6 +29,8 @@ static const struct pci_device_id b43_pc
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4322) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43222) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) },
 --- a/drivers/ssb/driver_chipcommon.c
 +++ b/drivers/ssb/driver_chipcommon.c
 @@ -3,7 +3,7 @@
@@ -216,6 +242,17 @@
 +		return 0;
 +	}
 +}
+--- a/drivers/ssb/driver_extif.c
++++ b/drivers/ssb/driver_extif.c
+@@ -3,7 +3,7 @@
+  * Broadcom EXTIF core driver
+  *
+  * Copyright 2005, Broadcom Corporation
+- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
++ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
+  * Copyright 2006, 2007, Felix Fietkau <nbd@openwrt.org>
+  * Copyright 2007, Aurelien Jarno <aurelien@aurel32.net>
+  *
 --- a/drivers/ssb/driver_gige.c
 +++ b/drivers/ssb/driver_gige.c
 @@ -3,7 +3,7 @@
@@ -261,6 +298,27 @@
  {
  	struct ssb_gige *dev;
  	u32 base, tmslow, tmshigh;
+--- a/drivers/ssb/driver_mipscore.c
++++ b/drivers/ssb/driver_mipscore.c
+@@ -3,7 +3,7 @@
+  * Broadcom MIPS core driver
+  *
+  * Copyright 2005, Broadcom Corporation
+- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
++ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
+  *
+  * Licensed under the GNU/GPL. See COPYING for details.
+  */
+@@ -208,6 +208,9 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m
+ 	struct ssb_bus *bus = mcore->dev->bus;
+ 	u32 pll_type, n, m, rate = 0;
+ 
++	if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU)
++		return ssb_pmu_get_cpu_clock(&bus->chipco);
++
+ 	if (bus->extif.dev) {
+ 		ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m);
+ 	} else if (bus->chipco.dev) {
 --- a/drivers/ssb/driver_pcicore.c
 +++ b/drivers/ssb/driver_pcicore.c
 @@ -3,7 +3,7 @@
@@ -635,6 +693,17 @@
  	}
  	pc->setup_done = 1;
  out:
+--- a/drivers/ssb/embedded.c
++++ b/drivers/ssb/embedded.c
+@@ -3,7 +3,7 @@
+  * Embedded systems support code
+  *
+  * Copyright 2005-2008, Broadcom Corporation
+- * Copyright 2006-2008, Michael Buesch <mb@bu3sch.de>
++ * Copyright 2006-2008, Michael Buesch <m@bues.ch>
+  *
+  * Licensed under the GNU/GPL. See COPYING for details.
+  */
 --- a/drivers/ssb/main.c
 +++ b/drivers/ssb/main.c
 @@ -3,7 +3,7 @@
@@ -929,7 +998,26 @@
   * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
   * Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
   * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
-@@ -331,7 +331,6 @@ static void sprom_extract_r123(struct ss
+@@ -178,6 +178,18 @@ err_pci:
+ #define SPEX(_outvar, _offset, _mask, _shift) \
+ 	SPEX16(_outvar, _offset, _mask, _shift)
+ 
++#define SPEX_ARRAY8(_field, _offset, _mask, _shift)	\
++	do {	\
++		SPEX(_field[0], _offset +  0, _mask, _shift);	\
++		SPEX(_field[1], _offset +  2, _mask, _shift);	\
++		SPEX(_field[2], _offset +  4, _mask, _shift);	\
++		SPEX(_field[3], _offset +  6, _mask, _shift);	\
++		SPEX(_field[4], _offset +  8, _mask, _shift);	\
++		SPEX(_field[5], _offset + 10, _mask, _shift);	\
++		SPEX(_field[6], _offset + 12, _mask, _shift);	\
++		SPEX(_field[7], _offset + 14, _mask, _shift);	\
++	} while (0)
++
+ 
+ static inline u8 ssb_crc8(u8 crc, u8 data)
+ {
+@@ -331,7 +343,6 @@ static void sprom_extract_r123(struct ss
  {
  	int i;
  	u16 v;
@@ -937,8 +1025,24 @@
  	u16 loc[3];
  
  	if (out->revision == 3)			/* rev 3 moved MAC */
-@@ -390,20 +389,12 @@ static void sprom_extract_r123(struct ss
+@@ -361,8 +372,9 @@ static void sprom_extract_r123(struct ss
+ 	SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
+ 	SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
+ 	SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
+-	SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
+-	     SSB_SPROM1_BINF_CCODE_SHIFT);
++	if (out->revision == 1)
++		SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
++		     SSB_SPROM1_BINF_CCODE_SHIFT);
+ 	SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
+ 	     SSB_SPROM1_BINF_ANTA_SHIFT);
+ 	SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
+@@ -388,22 +400,16 @@ static void sprom_extract_r123(struct ss
+ 	SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
+ 	if (out->revision >= 2)
  		SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
++	SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
++	SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
  
  	/* Extract the antenna gain values. */
 -	gain = r123_extract_antgain(out->revision, in,
@@ -964,7 +1068,27 @@
  }
  
  /* Revs 4 5 and 8 have partially shared layout */
-@@ -504,16 +495,14 @@ static void sprom_extract_r45(struct ssb
+@@ -464,14 +470,17 @@ static void sprom_extract_r45(struct ssb
+ 	SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
+ 	SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
+ 	     SSB_SPROM4_ETHPHY_ET1A_SHIFT);
++	SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
+ 	if (out->revision == 4) {
+-		SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
++		SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
++		SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
+ 		SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
+ 		SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
+ 		SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
+ 		SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
+ 	} else {
+-		SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0);
++		SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8);
++		SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0);
+ 		SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
+ 		SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
+ 		SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
+@@ -504,16 +513,14 @@ static void sprom_extract_r45(struct ssb
  	}
  
  	/* Extract the antenna gain values. */
@@ -985,7 +1109,7 @@
  
  	sprom_extract_r458(out, in);
  
-@@ -523,7 +512,13 @@ static void sprom_extract_r45(struct ssb
+@@ -523,14 +530,22 @@ static void sprom_extract_r45(struct ssb
  static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
  {
  	int i;
@@ -1000,7 +1124,17 @@
  
  	/* extract the MAC address */
  	for (i = 0; i < 3; i++) {
-@@ -596,16 +591,69 @@ static void sprom_extract_r8(struct ssb_
+ 		v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
+ 		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
+ 	}
+-	SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
++	SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
++	SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
++	SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
+ 	SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
+ 	SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
+ 	SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
+@@ -596,17 +611,127 @@ static void sprom_extract_r8(struct ssb_
  	SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
  
  	/* Extract the antenna gain values. */
@@ -1018,7 +1152,7 @@
  	     SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
 -	memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
 -	       sizeof(out->antenna_gain.ghz5));
-+
+ 
 +	/* Extract cores power info info */
 +	for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
 +		o = pwr_info_offset[i];
@@ -1073,10 +1207,68 @@
 +		SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
 +	SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
 +		SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
- 
++
++	SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
++	     SSB_SPROM8_LEDDC_ON_SHIFT);
++	SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
++	     SSB_SPROM8_LEDDC_OFF_SHIFT);
++
++	SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
++	     SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
++	SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
++	     SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
++	SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
++	     SSB_SPROM8_TXRXC_SWITCH_SHIFT);
++
++	SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
++
++	SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
++
++	SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
++	     SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
++	SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
++	     SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
++	SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
++	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
++	SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
++	SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
++	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
++	SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
++	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
++	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
++	SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
++	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
++	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
++	SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
++	     SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
++
++	SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
++	SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
++	SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
++	SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
++
++	SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
++	     SSB_SPROM8_THERMAL_TRESH_SHIFT);
++	SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
++	     SSB_SPROM8_THERMAL_OFFSET_SHIFT);
++	SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
++	     SSB_SPROM8_TEMPDELTA_PHYCAL,
++	     SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
++	SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
++	     SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
++	SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
++	     SSB_SPROM8_TEMPDELTA_HYSTERESIS,
++	     SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
  	sprom_extract_r458(out, in);
  
-@@ -662,7 +710,6 @@ static int sprom_extract(struct ssb_bus
+ 	/* TODO - get remaining rev 8 stuff needed */
+@@ -662,7 +787,6 @@ static int sprom_extract(struct ssb_bus
  static int ssb_pci_sprom_get(struct ssb_bus *bus,
  			     struct ssb_sprom *sprom)
  {
@@ -1084,7 +1276,7 @@
  	int err;
  	u16 *buf;
  
-@@ -707,10 +754,17 @@ static int ssb_pci_sprom_get(struct ssb_
+@@ -707,10 +831,17 @@ static int ssb_pci_sprom_get(struct ssb_
  		if (err) {
  			/* All CRC attempts failed.
  			 * Maybe there is no SPROM on the device?
@@ -1106,7 +1298,7 @@
  				err = 0;
  				goto out_free;
  			}
-@@ -728,12 +782,9 @@ out_free:
+@@ -728,12 +859,8 @@ out_free:
  static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
  				  struct ssb_boardinfo *bi)
  {
@@ -1118,7 +1310,6 @@
 -			     &bi->rev);
 +	bi->vendor = bus->host_pci->subsystem_vendor;
 +	bi->type = bus->host_pci->subsystem_device;
-+	bi->rev = bus->host_pci->revision;
  }
  
  int ssb_pci_get_invariants(struct ssb_bus *bus,
@@ -1153,6 +1344,36 @@
  {
  	driver->probe = ssb_pcihost_probe;
  	driver->remove = ssb_pcihost_remove;
+--- a/drivers/ssb/pcmcia.c
++++ b/drivers/ssb/pcmcia.c
+@@ -3,7 +3,7 @@
+  * PCMCIA-Hostbus related functions
+  *
+  * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+- * Copyright 2007-2008 Michael Buesch <mb@bu3sch.de>
++ * Copyright 2007-2008 Michael Buesch <m@bues.ch>
+  *
+  * Licensed under the GNU/GPL. See COPYING for details.
+  */
+@@ -676,14 +676,10 @@ static int ssb_pcmcia_do_get_invariants(
+ 	case SSB_PCMCIA_CIS_ANTGAIN:
+ 		GOTO_ERROR_ON(tuple->TupleDataLen != 2,
+ 			"antg tpl size");
+-		sprom->antenna_gain.ghz24.a0 = tuple->TupleData[1];
+-		sprom->antenna_gain.ghz24.a1 = tuple->TupleData[1];
+-		sprom->antenna_gain.ghz24.a2 = tuple->TupleData[1];
+-		sprom->antenna_gain.ghz24.a3 = tuple->TupleData[1];
+-		sprom->antenna_gain.ghz5.a0 = tuple->TupleData[1];
+-		sprom->antenna_gain.ghz5.a1 = tuple->TupleData[1];
+-		sprom->antenna_gain.ghz5.a2 = tuple->TupleData[1];
+-		sprom->antenna_gain.ghz5.a3 = tuple->TupleData[1];
++		sprom->antenna_gain.a0 = tuple->TupleData[1];
++		sprom->antenna_gain.a1 = tuple->TupleData[1];
++		sprom->antenna_gain.a2 = tuple->TupleData[1];
++		sprom->antenna_gain.a3 = tuple->TupleData[1];
+ 		break;
+ 	case SSB_PCMCIA_CIS_BFLAGS:
+ 		GOTO_ERROR_ON((tuple->TupleDataLen != 3) &&
 --- a/drivers/ssb/scan.c
 +++ b/drivers/ssb/scan.c
 @@ -2,7 +2,7 @@
@@ -1196,6 +1417,36 @@
  	if (!bus->nr_devices)
  		bus->nr_devices = chipid_to_nrcores(bus->chip_id);
  	if (bus->nr_devices > ARRAY_SIZE(bus->devices)) {
+--- a/drivers/ssb/sdio.c
++++ b/drivers/ssb/sdio.c
+@@ -6,7 +6,7 @@
+  *
+  * Based on drivers/ssb/pcmcia.c
+  * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+- * Copyright 2007-2008 Michael Buesch <mb@bu3sch.de>
++ * Copyright 2007-2008 Michael Buesch <m@bues.ch>
+  *
+  * Licensed under the GNU/GPL. See COPYING for details.
+  *
+@@ -551,14 +551,10 @@ int ssb_sdio_get_invariants(struct ssb_b
+ 			case SSB_SDIO_CIS_ANTGAIN:
+ 				GOTO_ERROR_ON(tuple->size != 2,
+ 					      "antg tpl size");
+-				sprom->antenna_gain.ghz24.a0 = tuple->data[1];
+-				sprom->antenna_gain.ghz24.a1 = tuple->data[1];
+-				sprom->antenna_gain.ghz24.a2 = tuple->data[1];
+-				sprom->antenna_gain.ghz24.a3 = tuple->data[1];
+-				sprom->antenna_gain.ghz5.a0 = tuple->data[1];
+-				sprom->antenna_gain.ghz5.a1 = tuple->data[1];
+-				sprom->antenna_gain.ghz5.a2 = tuple->data[1];
+-				sprom->antenna_gain.ghz5.a3 = tuple->data[1];
++				sprom->antenna_gain.a0 = tuple->data[1];
++				sprom->antenna_gain.a1 = tuple->data[1];
++				sprom->antenna_gain.a2 = tuple->data[1];
++				sprom->antenna_gain.a3 = tuple->data[1];
+ 				break;
+ 			case SSB_SDIO_CIS_BFLAGS:
+ 				GOTO_ERROR_ON((tuple->size != 3) &&
 --- a/drivers/ssb/sprom.c
 +++ b/drivers/ssb/sprom.c
 @@ -2,7 +2,7 @@
@@ -1356,7 +1607,7 @@
  	u8 rssisav2g;		/* 2GHz RSSI params */
  	u8 rssismc2g;
  	u8 rssismf2g;
-@@ -80,26 +91,104 @@ struct ssb_sprom {
+@@ -80,26 +91,103 @@ struct ssb_sprom {
  	u16 boardflags2_hi;	/* Board flags (bits 48-63) */
  	/* TODO store board flags in a single u64 */
  
@@ -1465,11 +1716,10 @@
  	u16 vendor;
  	u16 type;
 -	u16 rev;
-+	u8  rev;
  };
  
  
-@@ -229,10 +318,9 @@ struct ssb_driver {
+@@ -229,10 +317,9 @@ struct ssb_driver {
  #define drv_to_ssb_drv(_drv) container_of(_drv, struct ssb_driver, drv)
  
  extern int __ssb_driver_register(struct ssb_driver *drv, struct module *owner);
@@ -1483,7 +1733,7 @@
  extern void ssb_driver_unregister(struct ssb_driver *drv);
  
  
-@@ -308,7 +396,7 @@ struct ssb_bus {
+@@ -308,7 +395,7 @@ struct ssb_bus {
  
  	/* ID information about the Chip. */
  	u16 chip_id;
@@ -1492,7 +1742,7 @@
  	u16 sprom_offset;
  	u16 sprom_size;		/* number of words in sprom */
  	u8 chip_package;
-@@ -404,7 +492,9 @@ extern bool ssb_is_sprom_available(struc
+@@ -404,7 +491,9 @@ extern bool ssb_is_sprom_available(struc
  
  /* Set a fallback SPROM.
   * See kdoc at the function definition for complete documentation. */
@@ -1503,7 +1753,7 @@
  
  /* Suspend a SSB bus.
   * Call this from the parent bus suspend routine. */
-@@ -518,6 +608,7 @@ extern int ssb_bus_may_powerdown(struct
+@@ -518,6 +607,7 @@ extern int ssb_bus_may_powerdown(struct
   * Otherwise static always-on powercontrol will be used. */
  extern int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl);
  
@@ -1554,6 +1804,16 @@
  #define SSB_CHIPCO_HW_WORKAROUND	0x01E4 /* Hardware workaround (rev >= 20) */
  #define SSB_CHIPCO_UART0_DATA		0x0300
  #define SSB_CHIPCO_UART0_IMR		0x0304
+--- a/include/linux/ssb/ssb_driver_gige.h
++++ b/include/linux/ssb/ssb_driver_gige.h
+@@ -2,6 +2,7 @@
+ #define LINUX_SSB_DRIVER_GIGE_H_
+ 
+ #include <linux/ssb/ssb.h>
++#include <linux/bug.h>
+ #include <linux/pci.h>
+ #include <linux/spinlock.h>
+ 
 --- a/include/linux/ssb/ssb_regs.h
 +++ b/include/linux/ssb/ssb_regs.h
 @@ -97,7 +97,7 @@
@@ -1565,8 +1825,53 @@
  #define  SSB_TMSLOW_REJECT_23	0x00000004 /* Reject (Backplane rev 2.3) */
  #define  SSB_TMSLOW_CLOCK	0x00010000 /* Clock Enable */
  #define  SSB_TMSLOW_FGC		0x00020000 /* Force Gated Clocks On */
-@@ -432,6 +432,56 @@
+@@ -228,6 +228,7 @@
+ #define  SSB_SPROM1_AGAIN_BG_SHIFT	0
+ #define  SSB_SPROM1_AGAIN_A		0xFF00	/* A-PHY */
+ #define  SSB_SPROM1_AGAIN_A_SHIFT	8
++#define SSB_SPROM1_CCODE		0x0076
+ 
+ /* SPROM Revision 2 (inherits from rev 1) */
+ #define SSB_SPROM2_BFLHI		0x0038	/* Boardflags (high 16 bits) */
+@@ -267,6 +268,7 @@
+ #define  SSB_SPROM3_OFDMGPO		0x107A	/* G-PHY OFDM Power Offset (4 bytes, BigEndian) */
+ 
+ /* SPROM Revision 4 */
++#define SSB_SPROM4_BOARDREV		0x0042	/* Board revision */
+ #define SSB_SPROM4_BFLLO		0x0044	/* Boardflags (low 16 bits) */
+ #define SSB_SPROM4_BFLHI		0x0046  /* Board Flags Hi */
+ #define SSB_SPROM4_BFL2LO		0x0048	/* Board flags 2 (low 16 bits) */
+@@ -389,6 +391,11 @@
+ #define  SSB_SPROM8_GPIOB_P2		0x00FF	/* Pin 2 */
+ #define  SSB_SPROM8_GPIOB_P3		0xFF00	/* Pin 3 */
+ #define  SSB_SPROM8_GPIOB_P3_SHIFT	8
++#define SSB_SPROM8_LEDDC		0x009A
++#define  SSB_SPROM8_LEDDC_ON		0xFF00	/* oncount */
++#define  SSB_SPROM8_LEDDC_ON_SHIFT	8
++#define  SSB_SPROM8_LEDDC_OFF		0x00FF	/* offcount */
++#define  SSB_SPROM8_LEDDC_OFF_SHIFT	0
+ #define SSB_SPROM8_ANTAVAIL		0x009C  /* Antenna available bitfields*/
+ #define  SSB_SPROM8_ANTAVAIL_A		0xFF00	/* A-PHY bitfield */
+ #define  SSB_SPROM8_ANTAVAIL_A_SHIFT	8
+@@ -404,6 +411,13 @@
+ #define  SSB_SPROM8_AGAIN2_SHIFT	0
+ #define  SSB_SPROM8_AGAIN3		0xFF00	/* Antenna 3 */
+ #define  SSB_SPROM8_AGAIN3_SHIFT	8
++#define SSB_SPROM8_TXRXC		0x00A2
++#define  SSB_SPROM8_TXRXC_TXCHAIN	0x000f
++#define  SSB_SPROM8_TXRXC_TXCHAIN_SHIFT	0
++#define  SSB_SPROM8_TXRXC_RXCHAIN	0x00f0
++#define  SSB_SPROM8_TXRXC_RXCHAIN_SHIFT	4
++#define  SSB_SPROM8_TXRXC_SWITCH	0xff00
++#define  SSB_SPROM8_TXRXC_SWITCH_SHIFT	8
+ #define SSB_SPROM8_RSSIPARM2G		0x00A4	/* RSSI params for 2GHz */
+ #define  SSB_SPROM8_RSSISMF2G		0x000F
+ #define  SSB_SPROM8_RSSISMC2G		0x00F0
+@@ -430,8 +444,87 @@
+ #define  SSB_SPROM8_TRI5GH_SHIFT	8
+ #define SSB_SPROM8_RXPO			0x00AC  /* RX power offsets */
  #define  SSB_SPROM8_RXPO2G		0x00FF	/* 2GHz RX power offset */
++#define  SSB_SPROM8_RXPO2G_SHIFT	0
  #define  SSB_SPROM8_RXPO5G		0xFF00	/* 5GHz RX power offset */
  #define  SSB_SPROM8_RXPO5G_SHIFT	8
 +#define SSB_SPROM8_FEM2G		0x00AE
@@ -1582,10 +1887,38 @@
 +#define  SSB_SROM8_FEM_ANTSWLUT		0xF800
 +#define  SSB_SROM8_FEM_ANTSWLUT_SHIFT	11
 +#define SSB_SPROM8_THERMAL		0x00B2
-+#define SSB_SPROM8_MPWR_RAWTS		0x00B4
-+#define SSB_SPROM8_TS_SLP_OPT_CORRX	0x00B6
-+#define SSB_SPROM8_FOC_HWIQ_IQSWP	0x00B8
-+#define SSB_SPROM8_PHYCAL_TEMPDELTA	0x00BA
++#define  SSB_SPROM8_THERMAL_OFFSET	0x00ff
++#define  SSB_SPROM8_THERMAL_OFFSET_SHIFT	0
++#define  SSB_SPROM8_THERMAL_TRESH	0xff00
++#define  SSB_SPROM8_THERMAL_TRESH_SHIFT	8
++/* Temp sense related entries */
++#define SSB_SPROM8_RAWTS		0x00B4
++#define  SSB_SPROM8_RAWTS_RAWTEMP	0x01ff
++#define  SSB_SPROM8_RAWTS_RAWTEMP_SHIFT	0
++#define  SSB_SPROM8_RAWTS_MEASPOWER	0xfe00
++#define  SSB_SPROM8_RAWTS_MEASPOWER_SHIFT	9
++#define SSB_SPROM8_OPT_CORRX		0x00B6
++#define  SSB_SPROM8_OPT_CORRX_TEMP_SLOPE	0x00ff
++#define  SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT	0
++#define  SSB_SPROM8_OPT_CORRX_TEMPCORRX	0xfc00
++#define  SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT	10
++#define  SSB_SPROM8_OPT_CORRX_TEMP_OPTION	0x0300
++#define  SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT	8
++/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */
++#define SSB_SPROM8_HWIQ_IQSWP		0x00B8
++#define  SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR	0x000f
++#define  SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT	0
++#define  SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP	0x0010
++#define  SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT	4
++#define  SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL	0x0020
++#define  SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT	5
++#define SSB_SPROM8_TEMPDELTA		0x00BA
++#define  SSB_SPROM8_TEMPDELTA_PHYCAL	0x00ff
++#define  SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT	0
++#define  SSB_SPROM8_TEMPDELTA_PERIOD	0x0f00
++#define  SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT	8
++#define  SSB_SPROM8_TEMPDELTA_HYSTERESIS	0xf000
++#define  SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT	12
 +
 +/* There are 4 blocks with power info sharing the same layout */
 +#define SSB_SROM8_PWR_INFO_CORE0	0x00C0
@@ -1622,7 +1955,7 @@
  #define SSB_SPROM8_MAXP_BG		0x00C0  /* Max Power 2GHz in path 1 */
  #define  SSB_SPROM8_MAXP_BG_MASK	0x00FF  /* Mask for Max Power 2GHz */
  #define  SSB_SPROM8_ITSSI_BG		0xFF00	/* Mask for path 1 itssi_bg */
-@@ -456,12 +506,53 @@
+@@ -456,12 +549,63 @@
  #define SSB_SPROM8_PA1HIB0		0x00D8	/* 5.8GHz power amp settings */
  #define SSB_SPROM8_PA1HIB1		0x00DA
  #define SSB_SPROM8_PA1HIB2		0x00DC
@@ -1633,6 +1966,16 @@
  #define SSB_SPROM8_OFDM5GLPO		0x014A	/* 5.2GHz OFDM power offset */
  #define SSB_SPROM8_OFDM5GHPO		0x014E	/* 5.8GHz OFDM power offset */
  
++#define SSB_SPROM8_2G_MCSPO		0x0152
++#define SSB_SPROM8_5G_MCSPO		0x0162
++#define SSB_SPROM8_5GL_MCSPO		0x0172
++#define SSB_SPROM8_5GH_MCSPO		0x0182
++
++#define SSB_SPROM8_CDDPO		0x0192
++#define SSB_SPROM8_STBCPO		0x0194
++#define SSB_SPROM8_BW40PO		0x0196
++#define SSB_SPROM8_BWDUPPO		0x0198
++
 +/* Values for boardflags_lo read from SPROM */
 +#define SSB_BFL_BTCOEXIST		0x0001	/* implements Bluetooth coexistance */
 +#define SSB_BFL_PACTRL			0x0002	/* GPIO 9 controlling the PA */
@@ -1676,133 +2019,3 @@
  /* Values for SSB_SPROM1_BINF_CCODE */
  enum {
  	SSB_SPROM1CCODE_WORLD = 0,
---- a/drivers/ssb/b43_pci_bridge.c
-+++ b/drivers/ssb/b43_pci_bridge.c
-@@ -5,12 +5,13 @@
-  * because of its small size we include it in the SSB core
-  * instead of creating a standalone module.
-  *
-- * Copyright 2007  Michael Buesch <mb@bu3sch.de>
-+ * Copyright 2007  Michael Buesch <m@bues.ch>
-  *
-  * Licensed under the GNU/GPL. See COPYING for details.
-  */
- 
- #include <linux/pci.h>
-+#include <linux/module.h>
- #include <linux/ssb/ssb.h>
- 
- #include "ssb_private.h"
---- a/drivers/ssb/driver_extif.c
-+++ b/drivers/ssb/driver_extif.c
-@@ -3,7 +3,7 @@
-  * Broadcom EXTIF core driver
-  *
-  * Copyright 2005, Broadcom Corporation
-- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
-+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
-  * Copyright 2006, 2007, Felix Fietkau <nbd@openwrt.org>
-  * Copyright 2007, Aurelien Jarno <aurelien@aurel32.net>
-  *
---- a/drivers/ssb/driver_mipscore.c
-+++ b/drivers/ssb/driver_mipscore.c
-@@ -3,7 +3,7 @@
-  * Broadcom MIPS core driver
-  *
-  * Copyright 2005, Broadcom Corporation
-- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
-+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
-  *
-  * Licensed under the GNU/GPL. See COPYING for details.
-  */
-@@ -208,6 +208,9 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m
- 	struct ssb_bus *bus = mcore->dev->bus;
- 	u32 pll_type, n, m, rate = 0;
- 
-+	if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU)
-+		return ssb_pmu_get_cpu_clock(&bus->chipco);
-+
- 	if (bus->extif.dev) {
- 		ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m);
- 	} else if (bus->chipco.dev) {
---- a/drivers/ssb/embedded.c
-+++ b/drivers/ssb/embedded.c
-@@ -3,7 +3,7 @@
-  * Embedded systems support code
-  *
-  * Copyright 2005-2008, Broadcom Corporation
-- * Copyright 2006-2008, Michael Buesch <mb@bu3sch.de>
-+ * Copyright 2006-2008, Michael Buesch <m@bues.ch>
-  *
-  * Licensed under the GNU/GPL. See COPYING for details.
-  */
---- a/drivers/ssb/pcmcia.c
-+++ b/drivers/ssb/pcmcia.c
-@@ -3,7 +3,7 @@
-  * PCMCIA-Hostbus related functions
-  *
-  * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
-- * Copyright 2007-2008 Michael Buesch <mb@bu3sch.de>
-+ * Copyright 2007-2008 Michael Buesch <m@bues.ch>
-  *
-  * Licensed under the GNU/GPL. See COPYING for details.
-  */
-@@ -676,14 +676,10 @@ static int ssb_pcmcia_do_get_invariants(
- 	case SSB_PCMCIA_CIS_ANTGAIN:
- 		GOTO_ERROR_ON(tuple->TupleDataLen != 2,
- 			"antg tpl size");
--		sprom->antenna_gain.ghz24.a0 = tuple->TupleData[1];
--		sprom->antenna_gain.ghz24.a1 = tuple->TupleData[1];
--		sprom->antenna_gain.ghz24.a2 = tuple->TupleData[1];
--		sprom->antenna_gain.ghz24.a3 = tuple->TupleData[1];
--		sprom->antenna_gain.ghz5.a0 = tuple->TupleData[1];
--		sprom->antenna_gain.ghz5.a1 = tuple->TupleData[1];
--		sprom->antenna_gain.ghz5.a2 = tuple->TupleData[1];
--		sprom->antenna_gain.ghz5.a3 = tuple->TupleData[1];
-+		sprom->antenna_gain.a0 = tuple->TupleData[1];
-+		sprom->antenna_gain.a1 = tuple->TupleData[1];
-+		sprom->antenna_gain.a2 = tuple->TupleData[1];
-+		sprom->antenna_gain.a3 = tuple->TupleData[1];
- 		break;
- 	case SSB_PCMCIA_CIS_BFLAGS:
- 		GOTO_ERROR_ON((tuple->TupleDataLen != 3) &&
---- a/drivers/ssb/sdio.c
-+++ b/drivers/ssb/sdio.c
-@@ -6,7 +6,7 @@
-  *
-  * Based on drivers/ssb/pcmcia.c
-  * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
-- * Copyright 2007-2008 Michael Buesch <mb@bu3sch.de>
-+ * Copyright 2007-2008 Michael Buesch <m@bues.ch>
-  *
-  * Licensed under the GNU/GPL. See COPYING for details.
-  *
-@@ -551,14 +551,10 @@ int ssb_sdio_get_invariants(struct ssb_b
- 			case SSB_SDIO_CIS_ANTGAIN:
- 				GOTO_ERROR_ON(tuple->size != 2,
- 					      "antg tpl size");
--				sprom->antenna_gain.ghz24.a0 = tuple->data[1];
--				sprom->antenna_gain.ghz24.a1 = tuple->data[1];
--				sprom->antenna_gain.ghz24.a2 = tuple->data[1];
--				sprom->antenna_gain.ghz24.a3 = tuple->data[1];
--				sprom->antenna_gain.ghz5.a0 = tuple->data[1];
--				sprom->antenna_gain.ghz5.a1 = tuple->data[1];
--				sprom->antenna_gain.ghz5.a2 = tuple->data[1];
--				sprom->antenna_gain.ghz5.a3 = tuple->data[1];
-+				sprom->antenna_gain.a0 = tuple->data[1];
-+				sprom->antenna_gain.a1 = tuple->data[1];
-+				sprom->antenna_gain.a2 = tuple->data[1];
-+				sprom->antenna_gain.a3 = tuple->data[1];
- 				break;
- 			case SSB_SDIO_CIS_BFLAGS:
- 				GOTO_ERROR_ON((tuple->size != 3) &&
---- a/include/linux/ssb/ssb_driver_gige.h
-+++ b/include/linux/ssb/ssb_driver_gige.h
-@@ -2,6 +2,7 @@
- #define LINUX_SSB_DRIVER_GIGE_H_
- 
- #include <linux/ssb/ssb.h>
-+#include <linux/bug.h>
- #include <linux/pci.h>
- #include <linux/spinlock.h>
- 
diff --git a/target/linux/generic/patches-2.6.39/021-ssb_add_pci_id.patch b/target/linux/generic/patches-2.6.39/021-ssb_add_pci_id.patch
deleted file mode 100644
index 7cffebec48..0000000000
--- a/target/linux/generic/patches-2.6.39/021-ssb_add_pci_id.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/drivers/ssb/b43_pci_bridge.c
-+++ b/drivers/ssb/b43_pci_bridge.c
-@@ -29,6 +29,8 @@ static const struct pci_device_id b43_pc
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4322) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43222) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) },
diff --git a/target/linux/generic/patches-2.6.39/025-bcma_backport.patch b/target/linux/generic/patches-2.6.39/025-bcma_backport.patch
index 036f4199ad..937fc2f267 100644
--- a/target/linux/generic/patches-2.6.39/025-bcma_backport.patch
+++ b/target/linux/generic/patches-2.6.39/025-bcma_backport.patch
@@ -234,7 +234,7 @@
 +#endif
 --- /dev/null
 +++ b/drivers/bcma/core.c
-@@ -0,0 +1,126 @@
+@@ -0,0 +1,127 @@
 +/*
 + * Broadcom specific AMBA
 + * Core ops
@@ -266,6 +266,7 @@
 +	udelay(10);
 +
 +	bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
++	bcma_aread32(core, BCMA_RESET_CTL);
 +	udelay(1);
 +}
 +EXPORT_SYMBOL_GPL(bcma_core_disable);
@@ -313,7 +314,7 @@
 +			pr_err("HT force timeout\n");
 +		break;
 +	case BCMA_CLKMODE_DYNAMIC:
-+		pr_warn("Dynamic clockmode not supported yet!\n");
++		bcma_set32(core, BCMA_CLKCTLST, ~BCMA_CLKCTLST_FORCEHT);
 +		break;
 +	}
 +}
@@ -834,2588 +835,2604 @@
 +	return bcma_pmu_get_clockcontrol(cc);
 +}
 --- /dev/null
-+++ b/drivers/bcma/driver_pci.c
-@@ -0,0 +1,225 @@
++++ b/drivers/bcma/driver_mips.c
+@@ -0,0 +1,256 @@
 +/*
 + * Broadcom specific AMBA
-+ * PCI Core
++ * Broadcom MIPS32 74K core driver
 + *
-+ * Copyright 2005, 2011, Broadcom Corporation
-+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
-+ * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
++ * Copyright 2009, Broadcom Corporation
++ * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
++ * Copyright 2010, Bernhard Loos <bernhardloos@googlemail.com>
++ * Copyright 2011, Hauke Mehrtens <hauke@hauke-m.de>
 + *
 + * Licensed under the GNU/GPL. See COPYING for details.
 + */
 +
 +#include "bcma_private.h"
++
 +#include <linux/bcma/bcma.h>
 +
-+/**************************************************
-+ * R/W ops.
-+ **************************************************/
++#include <linux/serial.h>
++#include <linux/serial_core.h>
++#include <linux/serial_reg.h>
++#include <linux/time.h>
 +
-+u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address)
++/* The 47162a0 hangs when reading MIPS DMP registers registers */
++static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
 +{
-+	pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address);
-+	pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR);
-+	return pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_DATA);
++	return dev->bus->chipinfo.id == 47162 && dev->bus->chipinfo.rev == 0 &&
++	       dev->id.id == BCMA_CORE_MIPS_74K;
 +}
 +
-+#if 0
-+static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data)
++/* The 5357b0 hangs when reading USB20H DMP registers */
++static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev)
 +{
-+	pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address);
-+	pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR);
-+	pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_DATA, data);
++	return (dev->bus->chipinfo.id == 0x5357 ||
++		dev->bus->chipinfo.id == 0x4749) &&
++	       dev->bus->chipinfo.pkg == 11 &&
++	       dev->id.id == BCMA_CORE_USB20_HOST;
 +}
-+#endif
 +
-+static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy)
++static inline u32 mips_read32(struct bcma_drv_mips *mcore,
++			      u16 offset)
 +{
-+	u32 v;
-+	int i;
-+
-+	v = BCMA_CORE_PCI_MDIODATA_START;
-+	v |= BCMA_CORE_PCI_MDIODATA_WRITE;
-+	v |= (BCMA_CORE_PCI_MDIODATA_DEV_ADDR <<
-+	      BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF);
-+	v |= (BCMA_CORE_PCI_MDIODATA_BLK_ADDR <<
-+	      BCMA_CORE_PCI_MDIODATA_REGADDR_SHF);
-+	v |= BCMA_CORE_PCI_MDIODATA_TA;
-+	v |= (phy << 4);
-+	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v);
-+
-+	udelay(10);
-+	for (i = 0; i < 200; i++) {
-+		v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL);
-+		if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE)
-+			break;
-+		msleep(1);
-+	}
++	return bcma_read32(mcore->core, offset);
 +}
 +
-+static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address)
++static inline void mips_write32(struct bcma_drv_mips *mcore,
++				u16 offset,
++				u32 value)
 +{
-+	int max_retries = 10;
-+	u16 ret = 0;
-+	u32 v;
-+	int i;
++	bcma_write32(mcore->core, offset, value);
++}
 +
-+	/* enable mdio access to SERDES */
-+	v = BCMA_CORE_PCI_MDIOCTL_PREAM_EN;
-+	v |= BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL;
-+	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, v);
++static const u32 ipsflag_irq_mask[] = {
++	0,
++	BCMA_MIPS_IPSFLAG_IRQ1,
++	BCMA_MIPS_IPSFLAG_IRQ2,
++	BCMA_MIPS_IPSFLAG_IRQ3,
++	BCMA_MIPS_IPSFLAG_IRQ4,
++};
 +
-+	if (pc->core->id.rev >= 10) {
-+		max_retries = 200;
-+		bcma_pcie_mdio_set_phy(pc, device);
-+		v = (BCMA_CORE_PCI_MDIODATA_DEV_ADDR <<
-+		     BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF);
-+		v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF);
-+	} else {
-+		v = (device << BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD);
-+		v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD);
-+	}
++static const u32 ipsflag_irq_shift[] = {
++	0,
++	BCMA_MIPS_IPSFLAG_IRQ1_SHIFT,
++	BCMA_MIPS_IPSFLAG_IRQ2_SHIFT,
++	BCMA_MIPS_IPSFLAG_IRQ3_SHIFT,
++	BCMA_MIPS_IPSFLAG_IRQ4_SHIFT,
++};
 +
-+	v = BCMA_CORE_PCI_MDIODATA_START;
-+	v |= BCMA_CORE_PCI_MDIODATA_READ;
-+	v |= BCMA_CORE_PCI_MDIODATA_TA;
++static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
++{
++	u32 flag;
 +
-+	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v);
-+	/* Wait for the device to complete the transaction */
-+	udelay(10);
-+	for (i = 0; i < max_retries; i++) {
-+		v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL);
-+		if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) {
-+			udelay(10);
-+			ret = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_DATA);
-+			break;
-+		}
-+		msleep(1);
-+	}
-+	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0);
-+	return ret;
++	if (bcma_core_mips_bcm47162a0_quirk(dev))
++		return dev->core_index;
++	if (bcma_core_mips_bcm5357b0_quirk(dev))
++		return dev->core_index;
++	flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
++
++	return flag & 0x1F;
 +}
 +
-+static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device,
-+				u8 address, u16 data)
++/* Get the MIPS IRQ assignment for a specified device.
++ * If unassigned, 0 is returned.
++ */
++unsigned int bcma_core_mips_irq(struct bcma_device *dev)
 +{
-+	int max_retries = 10;
-+	u32 v;
-+	int i;
++	struct bcma_device *mdev = dev->bus->drv_mips.core;
++	u32 irqflag;
++	unsigned int irq;
 +
-+	/* enable mdio access to SERDES */
-+	v = BCMA_CORE_PCI_MDIOCTL_PREAM_EN;
-+	v |= BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL;
-+	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, v);
++	irqflag = bcma_core_mips_irqflag(dev);
 +
-+	if (pc->core->id.rev >= 10) {
-+		max_retries = 200;
-+		bcma_pcie_mdio_set_phy(pc, device);
-+		v = (BCMA_CORE_PCI_MDIODATA_DEV_ADDR <<
-+		     BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF);
-+		v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF);
-+	} else {
-+		v = (device << BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD);
-+		v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD);
-+	}
++	for (irq = 1; irq <= 4; irq++)
++		if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
++		    (1 << irqflag))
++			return irq;
 +
-+	v = BCMA_CORE_PCI_MDIODATA_START;
-+	v |= BCMA_CORE_PCI_MDIODATA_WRITE;
-+	v |= BCMA_CORE_PCI_MDIODATA_TA;
-+	v |= data;
-+	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v);
-+	/* Wait for the device to complete the transaction */
-+	udelay(10);
-+	for (i = 0; i < max_retries; i++) {
-+		v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL);
-+		if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE)
-+			break;
-+		msleep(1);
-+	}
-+	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0);
++	return 0;
 +}
++EXPORT_SYMBOL(bcma_core_mips_irq);
 +
-+/**************************************************
-+ * Workarounds.
-+ **************************************************/
-+
-+static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc)
++static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
 +{
-+	u32 tmp;
++	unsigned int oldirq = bcma_core_mips_irq(dev);
++	struct bcma_bus *bus = dev->bus;
++	struct bcma_device *mdev = bus->drv_mips.core;
++	u32 irqflag;
 +
-+	tmp = bcma_pcie_read(pc, BCMA_CORE_PCI_PLP_STATUSREG);
-+	if (tmp & BCMA_CORE_PCI_PLP_POLARITYINV_STAT)
-+		return BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE |
-+		       BCMA_CORE_PCI_SERDES_RX_CTRL_POLARITY;
++	irqflag = bcma_core_mips_irqflag(dev);
++	BUG_ON(oldirq == 6);
++
++	dev->irq = irq + 2;
++
++	/* clear the old irq */
++	if (oldirq == 0)
++		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
++			    bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
++			    ~(1 << irqflag));
 +	else
-+		return BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE;
-+}
++		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0);
 +
-+static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc)
-+{
-+	u16 tmp;
++	/* assign the new one */
++	if (irq == 0) {
++		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
++			    bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
++			    (1 << irqflag));
++	} else {
++		u32 oldirqflag = bcma_read32(mdev,
++					     BCMA_MIPS_MIPS74K_INTMASK(irq));
++		if (oldirqflag) {
++			struct bcma_device *core;
 +
-+	bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_RX,
-+	                     BCMA_CORE_PCI_SERDES_RX_CTRL,
-+			     bcma_pcicore_polarity_workaround(pc));
-+	tmp = bcma_pcie_mdio_read(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL,
-+	                          BCMA_CORE_PCI_SERDES_PLL_CTRL);
-+	if (tmp & BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN)
-+		bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL,
-+		                     BCMA_CORE_PCI_SERDES_PLL_CTRL,
-+		                     tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN);
-+}
++			/* backplane irq line is in use, find out who uses
++			 * it and set user to irq 0
++			 */
++			list_for_each_entry_reverse(core, &bus->cores, list) {
++				if ((1 << bcma_core_mips_irqflag(core)) ==
++				    oldirqflag) {
++					bcma_core_mips_set_irq(core, 0);
++					break;
++				}
++			}
++		}
++		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq),
++			     1 << irqflag);
++	}
 +
-+/**************************************************
-+ * Init.
-+ **************************************************/
++	pr_info("set_irq: core 0x%04x, irq %d => %d\n",
++		dev->id.id, oldirq + 2, irq + 2);
++}
 +
-+static void __devinit bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
++static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
 +{
-+	bcma_pcicore_serdes_workaround(pc);
++	int i;
++	static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
++	printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
++	for (i = 0; i <= 6; i++)
++		printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
++	printk("\n");
 +}
 +
-+void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc)
++static void bcma_core_mips_dump_irq(struct bcma_bus *bus)
 +{
-+	if (pc->setup_done)
-+		return;
++	struct bcma_device *core;
 +
-+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
-+	pc->hostmode = bcma_core_pci_is_in_hostmode(pc);
-+	if (pc->hostmode)
-+		bcma_core_pci_hostmode_init(pc);
-+#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
++	list_for_each_entry_reverse(core, &bus->cores, list) {
++		bcma_core_mips_print_irq(core, bcma_core_mips_irq(core));
++	}
++}
 +
-+	if (!pc->hostmode)
-+		bcma_core_pci_clientmode_init(pc);
++u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
++{
++	struct bcma_bus *bus = mcore->core->bus;
++
++	if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
++		return bcma_pmu_get_clockcpu(&bus->drv_cc);
++
++	pr_err("No PMU available, need this to get the cpu clock\n");
++	return 0;
 +}
++EXPORT_SYMBOL(bcma_cpu_clock);
 +
-+int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
-+			  bool enable)
++static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
 +{
-+	struct pci_dev *pdev = pc->core->bus->host_pci;
-+	u32 coremask, tmp;
-+	int err = 0;
++	struct bcma_bus *bus = mcore->core->bus;
 +
-+	if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) {
-+		/* This bcma device is not on a PCI host-bus. So the IRQs are
-+		 * not routed through the PCI core.
-+		 * So we must not enable routing through the PCI core. */
-+		goto out;
++	switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
++	case BCMA_CC_FLASHT_STSER:
++	case BCMA_CC_FLASHT_ATSER:
++		pr_err("Serial flash not supported.\n");
++		break;
++	case BCMA_CC_FLASHT_PARA:
++		pr_info("found parallel flash.\n");
++		bus->drv_cc.pflash.window = 0x1c000000;
++		bus->drv_cc.pflash.window_size = 0x02000000;
++
++		if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) &
++		     BCMA_CC_FLASH_CFG_DS) == 0)
++			bus->drv_cc.pflash.buswidth = 1;
++		else
++			bus->drv_cc.pflash.buswidth = 2;
++		break;
++	default:
++		pr_err("flash not supported.\n");
 +	}
++}
 +
-+	err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
-+	if (err)
-+		goto out;
++void bcma_core_mips_init(struct bcma_drv_mips *mcore)
++{
++	struct bcma_bus *bus;
++	struct bcma_device *core;
++	bus = mcore->core->bus;
 +
-+	coremask = BIT(core->core_index) << 8;
-+	if (enable)
-+		tmp |= coremask;
-+	else
-+		tmp &= ~coremask;
++	pr_info("Initializing MIPS core...\n");
 +
-+	err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp);
++	if (!mcore->setup_done)
++		mcore->assigned_irqs = 1;
 +
-+out:
-+	return err;
++	/* Assign IRQs to all cores on the bus */
++	list_for_each_entry_reverse(core, &bus->cores, list) {
++		int mips_irq;
++		if (core->irq)
++			continue;
++
++		mips_irq = bcma_core_mips_irq(core);
++		if (mips_irq > 4)
++			core->irq = 0;
++		else
++			core->irq = mips_irq + 2;
++		if (core->irq > 5)
++			continue;
++		switch (core->id.id) {
++		case BCMA_CORE_PCI:
++		case BCMA_CORE_PCIE:
++		case BCMA_CORE_ETHERNET:
++		case BCMA_CORE_ETHERNET_GBIT:
++		case BCMA_CORE_MAC_GBIT:
++		case BCMA_CORE_80211:
++		case BCMA_CORE_USB20_HOST:
++			/* These devices get their own IRQ line if available,
++			 * the rest goes on IRQ0
++			 */
++			if (mcore->assigned_irqs <= 4)
++				bcma_core_mips_set_irq(core,
++						       mcore->assigned_irqs++);
++			break;
++		}
++	}
++	pr_info("IRQ reconfiguration done\n");
++	bcma_core_mips_dump_irq(bus);
++
++	if (mcore->setup_done)
++		return;
++
++	bcma_chipco_serial_init(&bus->drv_cc);
++	bcma_core_mips_flash_detect(mcore);
++	mcore->setup_done = true;
 +}
-+EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
 --- /dev/null
-+++ b/drivers/bcma/host_pci.c
-@@ -0,0 +1,292 @@
++++ b/drivers/bcma/driver_pci.c
+@@ -0,0 +1,274 @@
 +/*
 + * Broadcom specific AMBA
-+ * PCI Host
++ * PCI Core
++ *
++ * Copyright 2005, 2011, Broadcom Corporation
++ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
++ * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
 + *
 + * Licensed under the GNU/GPL. See COPYING for details.
 + */
 +
 +#include "bcma_private.h"
-+#include <linux/slab.h>
 +#include <linux/bcma/bcma.h>
-+#include <linux/pci.h>
-+#include <linux/module.h>
 +
-+static void bcma_host_pci_switch_core(struct bcma_device *core)
-+{
-+	pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN,
-+			       core->addr);
-+	pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2,
-+			       core->wrap);
-+	core->bus->mapped_core = core;
-+	pr_debug("Switched to core: 0x%X\n", core->id.id);
-+}
++/**************************************************
++ * R/W ops.
++ **************************************************/
 +
-+/* Provides access to the requested core. Returns base offset that has to be
-+ * used. It makes use of fixed windows when possible. */
-+static u16 bcma_host_pci_provide_access_to_core(struct bcma_device *core)
++u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address)
 +{
-+	switch (core->id.id) {
-+	case BCMA_CORE_CHIPCOMMON:
-+		return 3 * BCMA_CORE_SIZE;
-+	case BCMA_CORE_PCIE:
-+		return 2 * BCMA_CORE_SIZE;
-+	}
-+
-+	if (core->bus->mapped_core != core)
-+		bcma_host_pci_switch_core(core);
-+	return 0;
++	pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address);
++	pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR);
++	return pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_DATA);
 +}
 +
-+static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset)
++static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data)
 +{
-+	offset += bcma_host_pci_provide_access_to_core(core);
-+	return ioread8(core->bus->mmio + offset);
++	pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address);
++	pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR);
++	pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_DATA, data);
 +}
 +
-+static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset)
++static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy)
 +{
-+	offset += bcma_host_pci_provide_access_to_core(core);
-+	return ioread16(core->bus->mmio + offset);
-+}
++	u32 v;
++	int i;
 +
-+static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset)
-+{
-+	offset += bcma_host_pci_provide_access_to_core(core);
-+	return ioread32(core->bus->mmio + offset);
-+}
++	v = BCMA_CORE_PCI_MDIODATA_START;
++	v |= BCMA_CORE_PCI_MDIODATA_WRITE;
++	v |= (BCMA_CORE_PCI_MDIODATA_DEV_ADDR <<
++	      BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF);
++	v |= (BCMA_CORE_PCI_MDIODATA_BLK_ADDR <<
++	      BCMA_CORE_PCI_MDIODATA_REGADDR_SHF);
++	v |= BCMA_CORE_PCI_MDIODATA_TA;
++	v |= (phy << 4);
++	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v);
 +
-+static void bcma_host_pci_write8(struct bcma_device *core, u16 offset,
-+				 u8 value)
-+{
-+	offset += bcma_host_pci_provide_access_to_core(core);
-+	iowrite8(value, core->bus->mmio + offset);
++	udelay(10);
++	for (i = 0; i < 200; i++) {
++		v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL);
++		if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE)
++			break;
++		msleep(1);
++	}
 +}
 +
-+static void bcma_host_pci_write16(struct bcma_device *core, u16 offset,
-+				 u16 value)
++static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address)
 +{
-+	offset += bcma_host_pci_provide_access_to_core(core);
-+	iowrite16(value, core->bus->mmio + offset);
-+}
++	int max_retries = 10;
++	u16 ret = 0;
++	u32 v;
++	int i;
 +
-+static void bcma_host_pci_write32(struct bcma_device *core, u16 offset,
-+				 u32 value)
-+{
-+	offset += bcma_host_pci_provide_access_to_core(core);
-+	iowrite32(value, core->bus->mmio + offset);
-+}
++	/* enable mdio access to SERDES */
++	v = BCMA_CORE_PCI_MDIOCTL_PREAM_EN;
++	v |= BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL;
++	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, v);
 +
-+#ifdef CONFIG_BCMA_BLOCKIO
-+void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
-+			      size_t count, u16 offset, u8 reg_width)
-+{
-+	void __iomem *addr = core->bus->mmio + offset;
-+	if (core->bus->mapped_core != core)
-+		bcma_host_pci_switch_core(core);
-+	switch (reg_width) {
-+	case sizeof(u8):
-+		ioread8_rep(addr, buffer, count);
-+		break;
-+	case sizeof(u16):
-+		WARN_ON(count & 1);
-+		ioread16_rep(addr, buffer, count >> 1);
-+		break;
-+	case sizeof(u32):
-+		WARN_ON(count & 3);
-+		ioread32_rep(addr, buffer, count >> 2);
-+		break;
-+	default:
-+		WARN_ON(1);
++	if (pc->core->id.rev >= 10) {
++		max_retries = 200;
++		bcma_pcie_mdio_set_phy(pc, device);
++		v = (BCMA_CORE_PCI_MDIODATA_DEV_ADDR <<
++		     BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF);
++		v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF);
++	} else {
++		v = (device << BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD);
++		v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD);
 +	}
-+}
 +
-+void bcma_host_pci_block_write(struct bcma_device *core, const void *buffer,
-+			       size_t count, u16 offset, u8 reg_width)
-+{
-+	void __iomem *addr = core->bus->mmio + offset;
-+	if (core->bus->mapped_core != core)
-+		bcma_host_pci_switch_core(core);
-+	switch (reg_width) {
-+	case sizeof(u8):
-+		iowrite8_rep(addr, buffer, count);
-+		break;
-+	case sizeof(u16):
-+		WARN_ON(count & 1);
-+		iowrite16_rep(addr, buffer, count >> 1);
-+		break;
-+	case sizeof(u32):
-+		WARN_ON(count & 3);
-+		iowrite32_rep(addr, buffer, count >> 2);
-+		break;
-+	default:
-+		WARN_ON(1);
++	v = BCMA_CORE_PCI_MDIODATA_START;
++	v |= BCMA_CORE_PCI_MDIODATA_READ;
++	v |= BCMA_CORE_PCI_MDIODATA_TA;
++
++	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v);
++	/* Wait for the device to complete the transaction */
++	udelay(10);
++	for (i = 0; i < max_retries; i++) {
++		v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL);
++		if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) {
++			udelay(10);
++			ret = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_DATA);
++			break;
++		}
++		msleep(1);
 +	}
++	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0);
++	return ret;
 +}
-+#endif
 +
-+static u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset)
++static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device,
++				u8 address, u16 data)
 +{
-+	if (core->bus->mapped_core != core)
-+		bcma_host_pci_switch_core(core);
-+	return ioread32(core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset);
-+}
++	int max_retries = 10;
++	u32 v;
++	int i;
 +
-+static void bcma_host_pci_awrite32(struct bcma_device *core, u16 offset,
-+				  u32 value)
-+{
-+	if (core->bus->mapped_core != core)
-+		bcma_host_pci_switch_core(core);
-+	iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset);
++	/* enable mdio access to SERDES */
++	v = BCMA_CORE_PCI_MDIOCTL_PREAM_EN;
++	v |= BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL;
++	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, v);
++
++	if (pc->core->id.rev >= 10) {
++		max_retries = 200;
++		bcma_pcie_mdio_set_phy(pc, device);
++		v = (BCMA_CORE_PCI_MDIODATA_DEV_ADDR <<
++		     BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF);
++		v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF);
++	} else {
++		v = (device << BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD);
++		v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD);
++	}
++
++	v = BCMA_CORE_PCI_MDIODATA_START;
++	v |= BCMA_CORE_PCI_MDIODATA_WRITE;
++	v |= BCMA_CORE_PCI_MDIODATA_TA;
++	v |= data;
++	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v);
++	/* Wait for the device to complete the transaction */
++	udelay(10);
++	for (i = 0; i < max_retries; i++) {
++		v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL);
++		if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE)
++			break;
++		msleep(1);
++	}
++	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0);
 +}
 +
-+const struct bcma_host_ops bcma_host_pci_ops = {
-+	.read8		= bcma_host_pci_read8,
-+	.read16		= bcma_host_pci_read16,
-+	.read32		= bcma_host_pci_read32,
-+	.write8		= bcma_host_pci_write8,
-+	.write16	= bcma_host_pci_write16,
-+	.write32	= bcma_host_pci_write32,
-+#ifdef CONFIG_BCMA_BLOCKIO
-+	.block_read	= bcma_host_pci_block_read,
-+	.block_write	= bcma_host_pci_block_write,
-+#endif
-+	.aread32	= bcma_host_pci_aread32,
-+	.awrite32	= bcma_host_pci_awrite32,
-+};
++/**************************************************
++ * Workarounds.
++ **************************************************/
 +
-+static int __devinit bcma_host_pci_probe(struct pci_dev *dev,
-+					 const struct pci_device_id *id)
++static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc)
 +{
-+	struct bcma_bus *bus;
-+	int err = -ENOMEM;
-+	const char *name;
-+	u32 val;
-+
-+	/* Alloc */
-+	bus = kzalloc(sizeof(*bus), GFP_KERNEL);
-+	if (!bus)
-+		goto out;
++	u32 tmp;
 +
-+	/* Basic PCI configuration */
-+	err = pci_enable_device(dev);
-+	if (err)
-+		goto err_kfree_bus;
++	tmp = bcma_pcie_read(pc, BCMA_CORE_PCI_PLP_STATUSREG);
++	if (tmp & BCMA_CORE_PCI_PLP_POLARITYINV_STAT)
++		return BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE |
++		       BCMA_CORE_PCI_SERDES_RX_CTRL_POLARITY;
++	else
++		return BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE;
++}
 +
-+	name = dev_name(&dev->dev);
-+	if (dev->driver && dev->driver->name)
-+		name = dev->driver->name;
-+	err = pci_request_regions(dev, name);
-+	if (err)
-+		goto err_pci_disable;
-+	pci_set_master(dev);
++static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc)
++{
++	u16 tmp;
 +
-+	/* Disable the RETRY_TIMEOUT register (0x41) to keep
-+	 * PCI Tx retries from interfering with C3 CPU state */
-+	pci_read_config_dword(dev, 0x40, &val);
-+	if ((val & 0x0000ff00) != 0)
-+		pci_write_config_dword(dev, 0x40, val & 0xffff00ff);
++	bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_RX,
++	                     BCMA_CORE_PCI_SERDES_RX_CTRL,
++			     bcma_pcicore_polarity_workaround(pc));
++	tmp = bcma_pcie_mdio_read(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL,
++	                          BCMA_CORE_PCI_SERDES_PLL_CTRL);
++	if (tmp & BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN)
++		bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL,
++		                     BCMA_CORE_PCI_SERDES_PLL_CTRL,
++		                     tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN);
++}
 +
-+	/* SSB needed additional powering up, do we have any AMBA PCI cards? */
-+	if (!pci_is_pcie(dev))
-+		pr_err("PCI card detected, report problems.\n");
++static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc)
++{
++	struct bcma_device *core = pc->core;
++	u16 val16, core_index;
++	uint regoff;
 +
-+	/* Map MMIO */
-+	err = -ENOMEM;
-+	bus->mmio = pci_iomap(dev, 0, ~0UL);
-+	if (!bus->mmio)
-+		goto err_pci_release_regions;
++	regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_PI_OFFSET);
++	core_index = (u16)core->core_index;
 +
-+	/* Host specific */
-+	bus->host_pci = dev;
-+	bus->hosttype = BCMA_HOSTTYPE_PCI;
-+	bus->ops = &bcma_host_pci_ops;
++	val16 = pcicore_read16(pc, regoff);
++	if (((val16 & BCMA_CORE_PCI_SPROM_PI_MASK) >> BCMA_CORE_PCI_SPROM_PI_SHIFT)
++	     != core_index) {
++		val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) |
++			(val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK);
++		pcicore_write16(pc, regoff, val16);
++	}
++}
 +
-+	/* Register */
-+	err = bcma_bus_register(bus);
-+	if (err)
-+		goto err_pci_unmap_mmio;
++/* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */
++/* Needs to happen when coming out of 'standby'/'hibernate' */
++static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc)
++{
++	u16 val16;
++	uint regoff;
 +
-+	pci_set_drvdata(dev, bus);
++	regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_MISC_CONFIG);
 +
-+out:
-+	return err;
++	val16 = pcicore_read16(pc, regoff);
 +
-+err_pci_unmap_mmio:
-+	pci_iounmap(dev, bus->mmio);
-+err_pci_release_regions:
-+	pci_release_regions(dev);
-+err_pci_disable:
-+	pci_disable_device(dev);
-+err_kfree_bus:
-+	kfree(bus);
-+	return err;
++	if (!(val16 & BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST)) {
++		val16 |= BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST;
++		pcicore_write16(pc, regoff, val16);
++	}
 +}
 +
-+static void bcma_host_pci_remove(struct pci_dev *dev)
-+{
-+	struct bcma_bus *bus = pci_get_drvdata(dev);
++/**************************************************
++ * Init.
++ **************************************************/
 +
-+	bcma_bus_unregister(bus);
-+	pci_iounmap(dev, bus->mmio);
-+	pci_release_regions(dev);
-+	pci_disable_device(dev);
-+	kfree(bus);
-+	pci_set_drvdata(dev, NULL);
++static void __devinit bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
++{
++	bcma_core_pci_fixcfg(pc);
++	bcma_pcicore_serdes_workaround(pc);
++	bcma_core_pci_config_fixup(pc);
 +}
 +
-+#ifdef CONFIG_PM
-+static int bcma_host_pci_suspend(struct device *dev)
++void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc)
 +{
-+	struct pci_dev *pdev = to_pci_dev(dev);
-+	struct bcma_bus *bus = pci_get_drvdata(pdev);
++	if (pc->setup_done)
++		return;
 +
-+	bus->mapped_core = NULL;
++#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
++	pc->hostmode = bcma_core_pci_is_in_hostmode(pc);
++	if (pc->hostmode)
++		bcma_core_pci_hostmode_init(pc);
++#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
 +
-+	return bcma_bus_suspend(bus);
++	if (!pc->hostmode)
++		bcma_core_pci_clientmode_init(pc);
 +}
 +
-+static int bcma_host_pci_resume(struct device *dev)
++int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
++			  bool enable)
 +{
-+	struct pci_dev *pdev = to_pci_dev(dev);
-+	struct bcma_bus *bus = pci_get_drvdata(pdev);
++	struct pci_dev *pdev = pc->core->bus->host_pci;
++	u32 coremask, tmp;
++	int err = 0;
 +
-+	return bcma_bus_resume(bus);
-+}
++	if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) {
++		/* This bcma device is not on a PCI host-bus. So the IRQs are
++		 * not routed through the PCI core.
++		 * So we must not enable routing through the PCI core. */
++		goto out;
++	}
 +
-+static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend,
-+			 bcma_host_pci_resume);
-+#define BCMA_PM_OPS	(&bcma_pm_ops)
++	err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
++	if (err)
++		goto out;
 +
-+#else /* CONFIG_PM */
++	coremask = BIT(core->core_index) << 8;
++	if (enable)
++		tmp |= coremask;
++	else
++		tmp &= ~coremask;
 +
-+#define BCMA_PM_OPS     NULL
++	err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp);
 +
-+#endif /* CONFIG_PM */
++out:
++	return err;
++}
++EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
 +
-+static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
-+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
-+	{ 0, },
-+};
-+MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl);
++void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend)
++{
++	u32 w;
 +
-+static struct pci_driver bcma_pci_bridge_driver = {
-+	.name = "bcma-pci-bridge",
-+	.id_table = bcma_pci_bridge_tbl,
-+	.probe = bcma_host_pci_probe,
-+	.remove = bcma_host_pci_remove,
-+	.driver.pm = BCMA_PM_OPS,
-+};
-+
-+int __init bcma_host_pci_init(void)
-+{
-+	return pci_register_driver(&bcma_pci_bridge_driver);
-+}
-+
-+void __exit bcma_host_pci_exit(void)
-+{
-+	pci_unregister_driver(&bcma_pci_bridge_driver);
++	w = bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG);
++	if (extend)
++		w |= BCMA_CORE_PCI_ASPMTIMER_EXTEND;
++	else
++		w &= ~BCMA_CORE_PCI_ASPMTIMER_EXTEND;
++	bcma_pcie_write(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG, w);
++	bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG);
 +}
++EXPORT_SYMBOL_GPL(bcma_core_pci_extend_L1timer);
 --- /dev/null
-+++ b/drivers/bcma/main.c
-@@ -0,0 +1,387 @@
++++ b/drivers/bcma/driver_pci_host.c
+@@ -0,0 +1,588 @@
 +/*
 + * Broadcom specific AMBA
-+ * Bus subsystem
++ * PCI Core in hostmode
++ *
++ * Copyright 2005 - 2011, Broadcom Corporation
++ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
++ * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
 + *
 + * Licensed under the GNU/GPL. See COPYING for details.
 + */
 +
 +#include "bcma_private.h"
-+#include <linux/module.h>
++#include <linux/pci.h>
 +#include <linux/bcma/bcma.h>
-+#include <linux/slab.h>
++#include <asm/paccess.h>
 +
-+MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
-+MODULE_LICENSE("GPL");
++/* Probe a 32bit value on the bus and catch bus exceptions.
++ * Returns nonzero on a bus exception.
++ * This is MIPS specific */
++#define mips_busprobe32(val, addr)	get_dbe((val), ((u32 *)(addr)))
 +
-+/* contains the number the next bus should get. */
-+static unsigned int bcma_bus_next_num = 0;
++/* Assume one-hot slot wiring */
++#define BCMA_PCI_SLOT_MAX	16
++#define	PCI_CONFIG_SPACE_SIZE	256
 +
-+/* bcma_buses_mutex locks the bcma_bus_next_num */
-+static DEFINE_MUTEX(bcma_buses_mutex);
++bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
++{
++	struct bcma_bus *bus = pc->core->bus;
++	u16 chipid_top;
++	u32 tmp;
 +
-+static int bcma_bus_match(struct device *dev, struct device_driver *drv);
-+static int bcma_device_probe(struct device *dev);
-+static int bcma_device_remove(struct device *dev);
-+static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env);
++	chipid_top = (bus->chipinfo.id & 0xFF00);
++	if (chipid_top != 0x4700 &&
++	    chipid_top != 0x5300)
++		return false;
 +
-+static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf)
-+{
-+	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
-+	return sprintf(buf, "0x%03X\n", core->id.manuf);
++	if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
++		pr_info("This PCI core is disabled and not working\n");
++		return false;
++	}
++
++	bcma_core_enable(pc->core, 0);
++
++	return !mips_busprobe32(tmp, pc->core->io_addr);
 +}
-+static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf)
++
++static u32 bcma_pcie_read_config(struct bcma_drv_pci *pc, u32 address)
 +{
-+	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
-+	return sprintf(buf, "0x%03X\n", core->id.id);
++	pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_ADDR, address);
++	pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_ADDR);
++	return pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_DATA);
 +}
-+static ssize_t rev_show(struct device *dev, struct device_attribute *attr, char *buf)
++
++static void bcma_pcie_write_config(struct bcma_drv_pci *pc, u32 address,
++				   u32 data)
 +{
-+	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
-+	return sprintf(buf, "0x%02X\n", core->id.rev);
++	pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_ADDR, address);
++	pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_ADDR);
++	pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_DATA, data);
 +}
-+static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf)
++
++static u32 bcma_get_cfgspace_addr(struct bcma_drv_pci *pc, unsigned int dev,
++			     unsigned int func, unsigned int off)
 +{
-+	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
-+	return sprintf(buf, "0x%X\n", core->id.class);
-+}
-+static struct device_attribute bcma_device_attrs[] = {
-+	__ATTR_RO(manuf),
-+	__ATTR_RO(id),
-+	__ATTR_RO(rev),
-+	__ATTR_RO(class),
-+	__ATTR_NULL,
-+};
++	u32 addr = 0;
 +
-+static struct bus_type bcma_bus_type = {
-+	.name		= "bcma",
-+	.match		= bcma_bus_match,
-+	.probe		= bcma_device_probe,
-+	.remove		= bcma_device_remove,
-+	.uevent		= bcma_device_uevent,
-+	.dev_attrs	= bcma_device_attrs,
-+};
++	/* Issue config commands only when the data link is up (atleast
++	 * one external pcie device is present).
++	 */
++	if (dev >= 2 || !(bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_LSREG)
++			  & BCMA_CORE_PCI_DLLP_LSREG_LINKUP))
++		goto out;
 +
-+struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
-+{
-+	struct bcma_device *core;
++	/* Type 0 transaction */
++	/* Slide the PCI window to the appropriate slot */
++	pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0);
++	/* Calculate the address */
++	addr = pc->host_controller->host_cfg_addr;
++	addr |= (dev << BCMA_CORE_PCI_CFG_SLOT_SHIFT);
++	addr |= (func << BCMA_CORE_PCI_CFG_FUN_SHIFT);
++	addr |= (off & ~3);
 +
-+	list_for_each_entry(core, &bus->cores, list) {
-+		if (core->id.id == coreid)
-+			return core;
-+	}
-+	return NULL;
++out:
++	return addr;
 +}
-+EXPORT_SYMBOL_GPL(bcma_find_core);
 +
-+static void bcma_release_core_dev(struct device *dev)
++static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev,
++				  unsigned int func, unsigned int off,
++				  void *buf, int len)
 +{
-+	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
-+	if (core->io_addr)
-+		iounmap(core->io_addr);
-+	if (core->io_wrap)
-+		iounmap(core->io_wrap);
-+	kfree(core);
-+}
++	int err = -EINVAL;
++	u32 addr, val;
++	void __iomem *mmio = 0;
 +
-+static int bcma_register_cores(struct bcma_bus *bus)
-+{
-+	struct bcma_device *core;
-+	int err, dev_id = 0;
++	WARN_ON(!pc->hostmode);
++	if (unlikely(len != 1 && len != 2 && len != 4))
++		goto out;
++	if (dev == 0) {
++		/* we support only two functions on device 0 */
++		if (func > 1)
++			return -EINVAL;
 +
-+	list_for_each_entry(core, &bus->cores, list) {
-+		/* We support that cores ourself */
-+		switch (core->id.id) {
-+		case BCMA_CORE_CHIPCOMMON:
-+		case BCMA_CORE_PCI:
-+		case BCMA_CORE_PCIE:
-+		case BCMA_CORE_MIPS_74K:
-+			continue;
++		/* accesses to config registers with offsets >= 256
++		 * requires indirect access.
++		 */
++		if (off >= PCI_CONFIG_SPACE_SIZE) {
++			addr = (func << 12);
++			addr |= (off & 0x0FFF);
++			val = bcma_pcie_read_config(pc, addr);
++		} else {
++			addr = BCMA_CORE_PCI_PCICFG0;
++			addr |= (func << 8);
++			addr |= (off & 0xfc);
++			val = pcicore_read32(pc, addr);
 +		}
++	} else {
++		addr = bcma_get_cfgspace_addr(pc, dev, func, off);
++		if (unlikely(!addr))
++			goto out;
++		err = -ENOMEM;
++		mmio = ioremap_nocache(addr, sizeof(val));
++		if (!mmio)
++			goto out;
 +
-+		core->dev.release = bcma_release_core_dev;
-+		core->dev.bus = &bcma_bus_type;
-+		dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id);
-+
-+		switch (bus->hosttype) {
-+		case BCMA_HOSTTYPE_PCI:
-+			core->dev.parent = &bus->host_pci->dev;
-+			core->dma_dev = &bus->host_pci->dev;
-+			core->irq = bus->host_pci->irq;
-+			break;
-+		case BCMA_HOSTTYPE_SOC:
-+			core->dev.dma_mask = &core->dev.coherent_dma_mask;
-+			core->dma_dev = &core->dev;
-+			break;
-+		case BCMA_HOSTTYPE_SDIO:
-+			break;
++		if (mips_busprobe32(val, mmio)) {
++			val = 0xffffffff;
++			goto unmap;
 +		}
 +
-+		err = device_register(&core->dev);
-+		if (err) {
-+			pr_err("Could not register dev for core 0x%03X\n",
-+			       core->id.id);
-+			continue;
-+		}
-+		core->dev_registered = true;
-+		dev_id++;
++		val = readl(mmio);
 +	}
++	val >>= (8 * (off & 3));
 +
-+	return 0;
-+}
-+
-+static void bcma_unregister_cores(struct bcma_bus *bus)
-+{
-+	struct bcma_device *core;
-+
-+	list_for_each_entry(core, &bus->cores, list) {
-+		if (core->dev_registered)
-+			device_unregister(&core->dev);
++	switch (len) {
++	case 1:
++		*((u8 *)buf) = (u8)val;
++		break;
++	case 2:
++		*((u16 *)buf) = (u16)val;
++		break;
++	case 4:
++		*((u32 *)buf) = (u32)val;
++		break;
 +	}
++	err = 0;
++unmap:
++	if (mmio)
++		iounmap(mmio);
++out:
++	return err;
 +}
 +
-+int __devinit bcma_bus_register(struct bcma_bus *bus)
++static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev,
++				   unsigned int func, unsigned int off,
++				   const void *buf, int len)
 +{
-+	int err;
-+	struct bcma_device *core;
-+
-+	mutex_lock(&bcma_buses_mutex);
-+	bus->num = bcma_bus_next_num++;
-+	mutex_unlock(&bcma_buses_mutex);
-+
-+	/* Scan for devices (cores) */
-+	err = bcma_bus_scan(bus);
-+	if (err) {
-+		pr_err("Failed to scan: %d\n", err);
-+		return -1;
-+	}
++	int err = -EINVAL;
++	u32 addr = 0, val = 0;
++	void __iomem *mmio = 0;
++	u16 chipid = pc->core->bus->chipinfo.id;
 +
-+	/* Init CC core */
-+	core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
-+	if (core) {
-+		bus->drv_cc.core = core;
-+		bcma_core_chipcommon_init(&bus->drv_cc);
++	WARN_ON(!pc->hostmode);
++	if (unlikely(len != 1 && len != 2 && len != 4))
++		goto out;
++	if (dev == 0) {
++		/* accesses to config registers with offsets >= 256
++		 * requires indirect access.
++		 */
++		if (off < PCI_CONFIG_SPACE_SIZE) {
++			addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0;
++			addr |= (func << 8);
++			addr |= (off & 0xfc);
++			mmio = ioremap_nocache(addr, sizeof(val));
++			if (!mmio)
++				goto out;
++		}
++	} else {
++		addr = bcma_get_cfgspace_addr(pc, dev, func, off);
++		if (unlikely(!addr))
++			goto out;
++		err = -ENOMEM;
++		mmio = ioremap_nocache(addr, sizeof(val));
++		if (!mmio)
++			goto out;
++
++		if (mips_busprobe32(val, mmio)) {
++			val = 0xffffffff;
++			goto unmap;
++		}
 +	}
 +
-+	/* Init MIPS core */
-+	core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
-+	if (core) {
-+		bus->drv_mips.core = core;
-+		bcma_core_mips_init(&bus->drv_mips);
++	switch (len) {
++	case 1:
++		val = readl(mmio);
++		val &= ~(0xFF << (8 * (off & 3)));
++		val |= *((const u8 *)buf) << (8 * (off & 3));
++		break;
++	case 2:
++		val = readl(mmio);
++		val &= ~(0xFFFF << (8 * (off & 3)));
++		val |= *((const u16 *)buf) << (8 * (off & 3));
++		break;
++	case 4:
++		val = *((const u32 *)buf);
++		break;
 +	}
++	if (dev == 0 && !addr) {
++		/* accesses to config registers with offsets >= 256
++		 * requires indirect access.
++		 */
++		addr = (func << 12);
++		addr |= (off & 0x0FFF);
++		bcma_pcie_write_config(pc, addr, val);
++	} else {
++		writel(val, mmio);
 +
-+	/* Init PCIE core */
-+	core = bcma_find_core(bus, BCMA_CORE_PCIE);
-+	if (core) {
-+		bus->drv_pci.core = core;
-+		bcma_core_pci_init(&bus->drv_pci);
++		if (chipid == 0x4716 || chipid == 0x4748)
++			readl(mmio);
 +	}
 +
-+	/* Try to get SPROM */
-+	err = bcma_sprom_get(bus);
-+	if (err == -ENOENT) {
-+		pr_err("No SPROM available\n");
-+	} else if (err)
-+		pr_err("Failed to get SPROM: %d\n", err);
++	err = 0;
++unmap:
++	if (mmio)
++		iounmap(mmio);
++out:
++	return err;
++}
 +
-+	/* Register found cores */
-+	bcma_register_cores(bus);
++static int bcma_core_pci_hostmode_read_config(struct pci_bus *bus,
++					      unsigned int devfn,
++					      int reg, int size, u32 *val)
++{
++	unsigned long flags;
++	int err;
++	struct bcma_drv_pci *pc;
++	struct bcma_drv_pci_host *pc_host;
 +
-+	pr_info("Bus registered\n");
++	pc_host = container_of(bus->ops, struct bcma_drv_pci_host, pci_ops);
++	pc = pc_host->pdev;
 +
-+	return 0;
-+}
++	spin_lock_irqsave(&pc_host->cfgspace_lock, flags);
++	err = bcma_extpci_read_config(pc, PCI_SLOT(devfn),
++				     PCI_FUNC(devfn), reg, val, size);
++	spin_unlock_irqrestore(&pc_host->cfgspace_lock, flags);
 +
-+void bcma_bus_unregister(struct bcma_bus *bus)
-+{
-+	bcma_unregister_cores(bus);
++	return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
 +}
 +
-+int __init bcma_bus_early_register(struct bcma_bus *bus,
-+				   struct bcma_device *core_cc,
-+				   struct bcma_device *core_mips)
++static int bcma_core_pci_hostmode_write_config(struct pci_bus *bus,
++					       unsigned int devfn,
++					       int reg, int size, u32 val)
 +{
++	unsigned long flags;
 +	int err;
-+	struct bcma_device *core;
-+	struct bcma_device_id match;
-+
-+	bcma_init_bus(bus);
-+
-+	match.manuf = BCMA_MANUF_BCM;
-+	match.id = BCMA_CORE_CHIPCOMMON;
-+	match.class = BCMA_CL_SIM;
-+	match.rev = BCMA_ANY_REV;
-+
-+	/* Scan for chip common core */
-+	err = bcma_bus_scan_early(bus, &match, core_cc);
-+	if (err) {
-+		pr_err("Failed to scan for common core: %d\n", err);
-+		return -1;
-+	}
++	struct bcma_drv_pci *pc;
++	struct bcma_drv_pci_host *pc_host;
 +
-+	match.manuf = BCMA_MANUF_MIPS;
-+	match.id = BCMA_CORE_MIPS_74K;
-+	match.class = BCMA_CL_SIM;
-+	match.rev = BCMA_ANY_REV;
++	pc_host = container_of(bus->ops, struct bcma_drv_pci_host, pci_ops);
++	pc = pc_host->pdev;
 +
-+	/* Scan for mips core */
-+	err = bcma_bus_scan_early(bus, &match, core_mips);
-+	if (err) {
-+		pr_err("Failed to scan for mips core: %d\n", err);
-+		return -1;
-+	}
++	spin_lock_irqsave(&pc_host->cfgspace_lock, flags);
++	err = bcma_extpci_write_config(pc, PCI_SLOT(devfn),
++				      PCI_FUNC(devfn), reg, &val, size);
++	spin_unlock_irqrestore(&pc_host->cfgspace_lock, flags);
 +
-+	/* Init CC core */
-+	core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
-+	if (core) {
-+		bus->drv_cc.core = core;
-+		bcma_core_chipcommon_init(&bus->drv_cc);
-+	}
++	return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
++}
 +
-+	/* Init MIPS core */
-+	core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
-+	if (core) {
-+		bus->drv_mips.core = core;
-+		bcma_core_mips_init(&bus->drv_mips);
-+	}
++/* return cap_offset if requested capability exists in the PCI config space */
++static u8 __devinit bcma_find_pci_capability(struct bcma_drv_pci *pc,
++					     unsigned int dev,
++					     unsigned int func, u8 req_cap_id,
++					     unsigned char *buf, u32 *buflen)
++{
++	u8 cap_id;
++	u8 cap_ptr = 0;
++	u32 bufsize;
++	u8 byte_val;
 +
-+	pr_info("Early bus registered\n");
++	/* check for Header type 0 */
++	bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val,
++				sizeof(u8));
++	if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL)
++		return cap_ptr;
 +
-+	return 0;
-+}
++	/* check if the capability pointer field exists */
++	bcma_extpci_read_config(pc, dev, func, PCI_STATUS, &byte_val,
++				sizeof(u8));
++	if (!(byte_val & PCI_STATUS_CAP_LIST))
++		return cap_ptr;
 +
-+#ifdef CONFIG_PM
-+int bcma_bus_suspend(struct bcma_bus *bus)
-+{
-+	struct bcma_device *core;
++	/* check if the capability pointer is 0x00 */
++	bcma_extpci_read_config(pc, dev, func, PCI_CAPABILITY_LIST, &cap_ptr,
++				sizeof(u8));
++	if (cap_ptr == 0x00)
++		return cap_ptr;
 +
-+	list_for_each_entry(core, &bus->cores, list) {
-+		struct device_driver *drv = core->dev.driver;
-+		if (drv) {
-+			struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
-+			if (adrv->suspend)
-+				adrv->suspend(core);
-+		}
++	/* loop thr'u the capability list and see if the requested capabilty
++	 * exists */
++	bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id, sizeof(u8));
++	while (cap_id != req_cap_id) {
++		bcma_extpci_read_config(pc, dev, func, cap_ptr + 1, &cap_ptr,
++					sizeof(u8));
++		if (cap_ptr == 0x00)
++			return cap_ptr;
++		bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id,
++					sizeof(u8));
 +	}
-+	return 0;
-+}
 +
-+int bcma_bus_resume(struct bcma_bus *bus)
-+{
-+	struct bcma_device *core;
++	/* found the caller requested capability */
++	if ((buf != NULL) && (buflen != NULL)) {
++		u8 cap_data;
 +
-+	/* Init CC core */
-+	core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
-+	if (core) {
-+		bus->drv_cc.setup_done = false;
-+		bcma_core_chipcommon_init(&bus->drv_cc);
-+	}
++		bufsize = *buflen;
++		if (!bufsize)
++			return cap_ptr;
 +
-+	list_for_each_entry(core, &bus->cores, list) {
-+		struct device_driver *drv = core->dev.driver;
-+		if (drv) {
-+			struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
-+			if (adrv->resume)
-+				adrv->resume(core);
++		*buflen = 0;
++
++		/* copy the cpability data excluding cap ID and next ptr */
++		cap_data = cap_ptr + 2;
++		if ((bufsize + cap_data)  > PCI_CONFIG_SPACE_SIZE)
++			bufsize = PCI_CONFIG_SPACE_SIZE - cap_data;
++		*buflen = bufsize;
++		while (bufsize--) {
++			bcma_extpci_read_config(pc, dev, func, cap_data, buf,
++						sizeof(u8));
++			cap_data++;
++			buf++;
 +		}
 +	}
 +
-+	return 0;
++	return cap_ptr;
 +}
-+#endif
 +
-+int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
++/* If the root port is capable of returning Config Request
++ * Retry Status (CRS) Completion Status to software then
++ * enable the feature.
++ */
++static void __devinit bcma_core_pci_enable_crs(struct bcma_drv_pci *pc)
 +{
-+	drv->drv.name = drv->name;
-+	drv->drv.bus = &bcma_bus_type;
-+	drv->drv.owner = owner;
++	u8 cap_ptr, root_ctrl, root_cap, dev;
++	u16 val16;
++	int i;
 +
-+	return driver_register(&drv->drv);
-+}
-+EXPORT_SYMBOL_GPL(__bcma_driver_register);
++	cap_ptr = bcma_find_pci_capability(pc, 0, 0, PCI_CAP_ID_EXP, NULL,
++					   NULL);
++	root_cap = cap_ptr + PCI_EXP_RTCAP;
++	bcma_extpci_read_config(pc, 0, 0, root_cap, &val16, sizeof(u16));
++	if (val16 & BCMA_CORE_PCI_RC_CRS_VISIBILITY) {
++		/* Enable CRS software visibility */
++		root_ctrl = cap_ptr + PCI_EXP_RTCTL;
++		val16 = PCI_EXP_RTCTL_CRSSVE;
++		bcma_extpci_read_config(pc, 0, 0, root_ctrl, &val16,
++					sizeof(u16));
 +
-+void bcma_driver_unregister(struct bcma_driver *drv)
-+{
-+	driver_unregister(&drv->drv);
++		/* Initiate a configuration request to read the vendor id
++		 * field of the device function's config space header after
++		 * 100 ms wait time from the end of Reset. If the device is
++		 * not done with its internal initialization, it must at
++		 * least return a completion TLP, with a completion status
++		 * of "Configuration Request Retry Status (CRS)". The root
++		 * complex must complete the request to the host by returning
++		 * a read-data value of 0001h for the Vendor ID field and
++		 * all 1s for any additional bytes included in the request.
++		 * Poll using the config reads for max wait time of 1 sec or
++		 * until we receive the successful completion status. Repeat
++		 * the procedure for all the devices.
++		 */
++		for (dev = 1; dev < BCMA_PCI_SLOT_MAX; dev++) {
++			for (i = 0; i < 100000; i++) {
++				bcma_extpci_read_config(pc, dev, 0,
++							PCI_VENDOR_ID, &val16,
++							sizeof(val16));
++				if (val16 != 0x1)
++					break;
++				udelay(10);
++			}
++			if (val16 == 0x1)
++				pr_err("PCI: Broken device in slot %d\n", dev);
++		}
++	}
 +}
-+EXPORT_SYMBOL_GPL(bcma_driver_unregister);
 +
-+static int bcma_bus_match(struct device *dev, struct device_driver *drv)
++void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
 +{
-+	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
-+	struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
-+	const struct bcma_device_id *cid = &core->id;
-+	const struct bcma_device_id *did;
++	struct bcma_bus *bus = pc->core->bus;
++	struct bcma_drv_pci_host *pc_host;
++	u32 tmp;
++	u32 pci_membase_1G;
++	unsigned long io_map_base;
 +
-+	for (did = adrv->id_table; did->manuf || did->id || did->rev; did++) {
-+	    if ((did->manuf == cid->manuf || did->manuf == BCMA_ANY_MANUF) &&
-+		(did->id == cid->id || did->id == BCMA_ANY_ID) &&
-+		(did->rev == cid->rev || did->rev == BCMA_ANY_REV) &&
-+		(did->class == cid->class || did->class == BCMA_ANY_CLASS))
-+			return 1;
++	pr_info("PCIEcore in host mode found\n");
++
++	pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL);
++	if (!pc_host)  {
++		pr_err("can not allocate memory");
++		return;
 +	}
-+	return 0;
-+}
 +
-+static int bcma_device_probe(struct device *dev)
-+{
-+	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
-+	struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
-+					       drv);
-+	int err = 0;
++	pc->host_controller = pc_host;
++	pc_host->pci_controller.io_resource = &pc_host->io_resource;
++	pc_host->pci_controller.mem_resource = &pc_host->mem_resource;
++	pc_host->pci_controller.pci_ops = &pc_host->pci_ops;
++	pc_host->pdev = pc;
 +
-+	if (adrv->probe)
-+		err = adrv->probe(core);
++	pci_membase_1G = BCMA_SOC_PCI_DMA;
++	pc_host->host_cfg_addr = BCMA_SOC_PCI_CFG;
 +
-+	return err;
-+}
++	pc_host->pci_ops.read = bcma_core_pci_hostmode_read_config;
++	pc_host->pci_ops.write = bcma_core_pci_hostmode_write_config;
 +
-+static int bcma_device_remove(struct device *dev)
-+{
-+	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
-+	struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
-+					       drv);
++	pc_host->mem_resource.name = "BCMA PCIcore external memory",
++	pc_host->mem_resource.start = BCMA_SOC_PCI_DMA;
++	pc_host->mem_resource.end = BCMA_SOC_PCI_DMA + BCMA_SOC_PCI_DMA_SZ - 1;
++	pc_host->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;
 +
-+	if (adrv->remove)
-+		adrv->remove(core);
++	pc_host->io_resource.name = "BCMA PCIcore external I/O",
++	pc_host->io_resource.start = 0x100;
++	pc_host->io_resource.end = 0x7FF;
++	pc_host->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED;
 +
-+	return 0;
-+}
++	/* Reset RC */
++	udelay(3000);
++	pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE);
++	udelay(1000);
++	pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST |
++			BCMA_CORE_PCI_CTL_RST_OE);
 +
-+static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env)
-+{
-+	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
++	/* 64 MB I/O access window. On 4716, use
++	 * sbtopcie0 to access the device registers. We
++	 * can't use address match 2 (1 GB window) region
++	 * as mips can't generate 64-bit address on the
++	 * backplane.
++	 */
++	if (bus->chipinfo.id == 0x4716 || bus->chipinfo.id == 0x4748) {
++		pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
++		pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
++					    BCMA_SOC_PCI_MEM_SZ - 1;
++		pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
++				BCMA_CORE_PCI_SBTOPCI_MEM | BCMA_SOC_PCI_MEM);
++	} else if (bus->chipinfo.id == 0x5300) {
++		tmp = BCMA_CORE_PCI_SBTOPCI_MEM;
++		tmp |= BCMA_CORE_PCI_SBTOPCI_PREF;
++		tmp |= BCMA_CORE_PCI_SBTOPCI_BURST;
++		if (pc->core->core_unit == 0) {
++			pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
++			pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
++						    BCMA_SOC_PCI_MEM_SZ - 1;
++			pci_membase_1G = BCMA_SOC_PCIE_DMA_H32;
++			pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
++					tmp | BCMA_SOC_PCI_MEM);
++		} else if (pc->core->core_unit == 1) {
++			pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM;
++			pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM +
++						    BCMA_SOC_PCI_MEM_SZ - 1;
++			pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32;
++			pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG;
++			pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
++					tmp | BCMA_SOC_PCI1_MEM);
++		}
++	} else
++		pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
++				BCMA_CORE_PCI_SBTOPCI_IO);
 +
-+	return add_uevent_var(env,
-+			      "MODALIAS=bcma:m%04Xid%04Xrev%02Xcl%02X",
-+			      core->id.manuf, core->id.id,
-+			      core->id.rev, core->id.class);
++	/* 64 MB configuration access window */
++	pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0);
++
++	/* 1 GB memory access window */
++	pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI2,
++			BCMA_CORE_PCI_SBTOPCI_MEM | pci_membase_1G);
++
++
++	/* As per PCI Express Base Spec 1.1 we need to wait for
++	 * at least 100 ms from the end of a reset (cold/warm/hot)
++	 * before issuing configuration requests to PCI Express
++	 * devices.
++	 */
++	udelay(100000);
++
++	bcma_core_pci_enable_crs(pc);
++
++	/* Enable PCI bridge BAR0 memory & master access */
++	tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
++	bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp));
++
++	/* Enable PCI interrupts */
++	pcicore_write32(pc, BCMA_CORE_PCI_IMASK, BCMA_CORE_PCI_IMASK_INTA);
++
++	/* Ok, ready to run, register it to the system.
++	 * The following needs change, if we want to port hostmode
++	 * to non-MIPS platform. */
++	io_map_base = (unsigned long)ioremap_nocache(pc_host->mem_resource.start,
++						     resource_size(&pc_host->mem_resource));
++	pc_host->pci_controller.io_map_base = io_map_base;
++	set_io_port_base(pc_host->pci_controller.io_map_base);
++	/* Give some time to the PCI controller to configure itself with the new
++	 * values. Not waiting at this point causes crashes of the machine. */
++	mdelay(10);
++	register_pci_controller(&pc_host->pci_controller);
++	return;
 +}
 +
-+static int __init bcma_modinit(void)
++/* Early PCI fixup for a device on the PCI-core bridge. */
++static void bcma_core_pci_fixup_pcibridge(struct pci_dev *dev)
 +{
-+	int err;
++	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
++		/* This is not a device on the PCI-core bridge. */
++		return;
++	}
++	if (PCI_SLOT(dev->devfn) != 0)
++		return;
 +
-+	err = bus_register(&bcma_bus_type);
-+	if (err)
-+		return err;
++	pr_info("PCI: Fixing up bridge %s\n", pci_name(dev));
 +
-+#ifdef CONFIG_BCMA_HOST_PCI
-+	err = bcma_host_pci_init();
-+	if (err) {
-+		pr_err("PCI host initialization failed\n");
-+		err = 0;
++	/* Enable PCI bridge bus mastering and memory space */
++	pci_set_master(dev);
++	if (pcibios_enable_device(dev, ~0) < 0) {
++		pr_err("PCI: BCMA bridge enable failed\n");
++		return;
 +	}
-+#endif
 +
-+	return err;
++	/* Enable PCI bridge BAR1 prefetch and burst */
++	pci_write_config_dword(dev, BCMA_PCI_BAR1_CONTROL, 3);
 +}
-+fs_initcall(bcma_modinit);
++DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_pcibridge);
 +
-+static void __exit bcma_modexit(void)
++/* Early PCI fixup for all PCI-cores to set the correct memory address. */
++static void bcma_core_pci_fixup_addresses(struct pci_dev *dev)
 +{
-+#ifdef CONFIG_BCMA_HOST_PCI
-+	bcma_host_pci_exit();
-+#endif
-+	bus_unregister(&bcma_bus_type);
-+}
-+module_exit(bcma_modexit)
---- /dev/null
-+++ b/drivers/bcma/scan.c
-@@ -0,0 +1,507 @@
-+/*
-+ * Broadcom specific AMBA
-+ * Bus scanning
-+ *
-+ * Licensed under the GNU/GPL. See COPYING for details.
-+ */
++	struct resource *res;
++	int pos;
 +
-+#include "scan.h"
-+#include "bcma_private.h"
++	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
++		/* This is not a device on the PCI-core bridge. */
++		return;
++	}
++	if (PCI_SLOT(dev->devfn) == 0)
++		return;
 +
-+#include <linux/bcma/bcma.h>
-+#include <linux/bcma/bcma_regs.h>
-+#include <linux/pci.h>
-+#include <linux/io.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/slab.h>
++	pr_info("PCI: Fixing up addresses %s\n", pci_name(dev));
 +
-+struct bcma_device_id_name {
-+	u16 id;
-+	const char *name;
-+};
-+struct bcma_device_id_name bcma_device_names[] = {
-+	{ BCMA_CORE_OOB_ROUTER, "OOB Router" },
-+	{ BCMA_CORE_INVALID, "Invalid" },
-+	{ BCMA_CORE_CHIPCOMMON, "ChipCommon" },
-+	{ BCMA_CORE_ILINE20, "ILine 20" },
-+	{ BCMA_CORE_SRAM, "SRAM" },
-+	{ BCMA_CORE_SDRAM, "SDRAM" },
-+	{ BCMA_CORE_PCI, "PCI" },
-+	{ BCMA_CORE_MIPS, "MIPS" },
-+	{ BCMA_CORE_ETHERNET, "Fast Ethernet" },
-+	{ BCMA_CORE_V90, "V90" },
-+	{ BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" },
-+	{ BCMA_CORE_ADSL, "ADSL" },
-+	{ BCMA_CORE_ILINE100, "ILine 100" },
-+	{ BCMA_CORE_IPSEC, "IPSEC" },
-+	{ BCMA_CORE_UTOPIA, "UTOPIA" },
-+	{ BCMA_CORE_PCMCIA, "PCMCIA" },
-+	{ BCMA_CORE_INTERNAL_MEM, "Internal Memory" },
-+	{ BCMA_CORE_MEMC_SDRAM, "MEMC SDRAM" },
-+	{ BCMA_CORE_OFDM, "OFDM" },
-+	{ BCMA_CORE_EXTIF, "EXTIF" },
-+	{ BCMA_CORE_80211, "IEEE 802.11" },
-+	{ BCMA_CORE_PHY_A, "PHY A" },
-+	{ BCMA_CORE_PHY_B, "PHY B" },
-+	{ BCMA_CORE_PHY_G, "PHY G" },
-+	{ BCMA_CORE_MIPS_3302, "MIPS 3302" },
-+	{ BCMA_CORE_USB11_HOST, "USB 1.1 Host" },
-+	{ BCMA_CORE_USB11_DEV, "USB 1.1 Device" },
-+	{ BCMA_CORE_USB20_HOST, "USB 2.0 Host" },
-+	{ BCMA_CORE_USB20_DEV, "USB 2.0 Device" },
-+	{ BCMA_CORE_SDIO_HOST, "SDIO Host" },
-+	{ BCMA_CORE_ROBOSWITCH, "Roboswitch" },
-+	{ BCMA_CORE_PARA_ATA, "PATA" },
-+	{ BCMA_CORE_SATA_XORDMA, "SATA XOR-DMA" },
-+	{ BCMA_CORE_ETHERNET_GBIT, "GBit Ethernet" },
-+	{ BCMA_CORE_PCIE, "PCIe" },
-+	{ BCMA_CORE_PHY_N, "PHY N" },
-+	{ BCMA_CORE_SRAM_CTL, "SRAM Controller" },
-+	{ BCMA_CORE_MINI_MACPHY, "Mini MACPHY" },
-+	{ BCMA_CORE_ARM_1176, "ARM 1176" },
-+	{ BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },
-+	{ BCMA_CORE_PHY_LP, "PHY LP" },
-+	{ BCMA_CORE_PMU, "PMU" },
-+	{ BCMA_CORE_PHY_SSN, "PHY SSN" },
-+	{ BCMA_CORE_SDIO_DEV, "SDIO Device" },
-+	{ BCMA_CORE_ARM_CM3, "ARM CM3" },
-+	{ BCMA_CORE_PHY_HT, "PHY HT" },
-+	{ BCMA_CORE_MIPS_74K, "MIPS 74K" },
-+	{ BCMA_CORE_MAC_GBIT, "GBit MAC" },
-+	{ BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" },
-+	{ BCMA_CORE_PCIE_RC, "PCIe Root Complex" },
-+	{ BCMA_CORE_OCP_OCP_BRIDGE, "OCP to OCP Bridge" },
-+	{ BCMA_CORE_SHARED_COMMON, "Common Shared" },
-+	{ BCMA_CORE_OCP_AHB_BRIDGE, "OCP to AHB Bridge" },
-+	{ BCMA_CORE_SPI_HOST, "SPI Host" },
-+	{ BCMA_CORE_I2S, "I2S" },
-+	{ BCMA_CORE_SDR_DDR1_MEM_CTL, "SDR/DDR1 Memory Controller" },
-+	{ BCMA_CORE_SHIM, "SHIM" },
-+	{ BCMA_CORE_DEFAULT, "Default" },
-+};
-+const char *bcma_device_name(struct bcma_device_id *id)
++	for (pos = 0; pos < 6; pos++) {
++		res = &dev->resource[pos];
++		if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM))
++			pci_assign_resource(dev, pos);
++	}
++}
++DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses);
++
++/* This function is called when doing a pci_enable_device().
++ * We must first check if the device is a device on the PCI-core bridge. */
++int bcma_core_pci_plat_dev_init(struct pci_dev *dev)
 +{
-+	int i;
++	struct bcma_drv_pci_host *pc_host;
 +
-+	if (id->manuf == BCMA_MANUF_BCM) {
-+		for (i = 0; i < ARRAY_SIZE(bcma_device_names); i++) {
-+			if (bcma_device_names[i].id == id->id)
-+				return bcma_device_names[i].name;
-+		}
++	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
++		/* This is not a device on the PCI-core bridge. */
++		return -ENODEV;
 +	}
-+	return "UNKNOWN";
++	pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
++			       pci_ops);
++
++	pr_info("PCI: Fixing up device %s\n", pci_name(dev));
++
++	/* Fix up interrupt lines */
++	dev->irq = bcma_core_mips_irq(pc_host->pdev->core) + 2;
++	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
++
++	return 0;
 +}
++EXPORT_SYMBOL(bcma_core_pci_plat_dev_init);
 +
-+static u32 bcma_scan_read32(struct bcma_bus *bus, u8 current_coreidx,
-+		       u16 offset)
++/* PCI device IRQ mapping. */
++int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev)
 +{
-+	return readl(bus->mmio + offset);
++	struct bcma_drv_pci_host *pc_host;
++
++	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
++		/* This is not a device on the PCI-core bridge. */
++		return -ENODEV;
++	}
++
++	pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
++			       pci_ops);
++	return bcma_core_mips_irq(pc_host->pdev->core) + 2;
 +}
++EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq);
+--- /dev/null
++++ b/drivers/bcma/host_pci.c
+@@ -0,0 +1,295 @@
++/*
++ * Broadcom specific AMBA
++ * PCI Host
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
 +
-+static void bcma_scan_switch_core(struct bcma_bus *bus, u32 addr)
++#include "bcma_private.h"
++#include <linux/slab.h>
++#include <linux/bcma/bcma.h>
++#include <linux/pci.h>
++#include <linux/module.h>
++
++static void bcma_host_pci_switch_core(struct bcma_device *core)
 +{
-+	if (bus->hosttype == BCMA_HOSTTYPE_PCI)
-+		pci_write_config_dword(bus->host_pci, BCMA_PCI_BAR0_WIN,
-+				       addr);
++	pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN,
++			       core->addr);
++	pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2,
++			       core->wrap);
++	core->bus->mapped_core = core;
++	pr_debug("Switched to core: 0x%X\n", core->id.id);
 +}
 +
-+static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 **eromptr)
++/* Provides access to the requested core. Returns base offset that has to be
++ * used. It makes use of fixed windows when possible. */
++static u16 bcma_host_pci_provide_access_to_core(struct bcma_device *core)
 +{
-+	u32 ent = readl(*eromptr);
-+	(*eromptr)++;
-+	return ent;
++	switch (core->id.id) {
++	case BCMA_CORE_CHIPCOMMON:
++		return 3 * BCMA_CORE_SIZE;
++	case BCMA_CORE_PCIE:
++		return 2 * BCMA_CORE_SIZE;
++	}
++
++	if (core->bus->mapped_core != core)
++		bcma_host_pci_switch_core(core);
++	return 0;
 +}
 +
-+static void bcma_erom_push_ent(u32 **eromptr)
++static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset)
 +{
-+	(*eromptr)--;
++	offset += bcma_host_pci_provide_access_to_core(core);
++	return ioread8(core->bus->mmio + offset);
 +}
 +
-+static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr)
++static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset)
 +{
-+	u32 ent = bcma_erom_get_ent(bus, eromptr);
-+	if (!(ent & SCAN_ER_VALID))
-+		return -ENOENT;
-+	if ((ent & SCAN_ER_TAG) != SCAN_ER_TAG_CI)
-+		return -ENOENT;
-+	return ent;
++	offset += bcma_host_pci_provide_access_to_core(core);
++	return ioread16(core->bus->mmio + offset);
 +}
 +
-+static bool bcma_erom_is_end(struct bcma_bus *bus, u32 **eromptr)
++static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset)
 +{
-+	u32 ent = bcma_erom_get_ent(bus, eromptr);
-+	bcma_erom_push_ent(eromptr);
-+	return (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID));
++	offset += bcma_host_pci_provide_access_to_core(core);
++	return ioread32(core->bus->mmio + offset);
 +}
 +
-+static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 **eromptr)
++static void bcma_host_pci_write8(struct bcma_device *core, u16 offset,
++				 u8 value)
 +{
-+	u32 ent = bcma_erom_get_ent(bus, eromptr);
-+	bcma_erom_push_ent(eromptr);
-+	return (((ent & SCAN_ER_VALID)) &&
-+		((ent & SCAN_ER_TAGX) == SCAN_ER_TAG_ADDR) &&
-+		((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE));
++	offset += bcma_host_pci_provide_access_to_core(core);
++	iowrite8(value, core->bus->mmio + offset);
 +}
 +
-+static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr)
++static void bcma_host_pci_write16(struct bcma_device *core, u16 offset,
++				 u16 value)
 +{
-+	u32 ent;
-+	while (1) {
-+		ent = bcma_erom_get_ent(bus, eromptr);
-+		if ((ent & SCAN_ER_VALID) &&
-+		    ((ent & SCAN_ER_TAG) == SCAN_ER_TAG_CI))
-+			break;
-+		if (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID))
-+			break;
-+	}
-+	bcma_erom_push_ent(eromptr);
++	offset += bcma_host_pci_provide_access_to_core(core);
++	iowrite16(value, core->bus->mmio + offset);
 +}
 +
-+static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr)
++static void bcma_host_pci_write32(struct bcma_device *core, u16 offset,
++				 u32 value)
 +{
-+	u32 ent = bcma_erom_get_ent(bus, eromptr);
-+	if (!(ent & SCAN_ER_VALID))
-+		return -ENOENT;
-+	if ((ent & SCAN_ER_TAG) != SCAN_ER_TAG_MP)
-+		return -ENOENT;
-+	return ent;
++	offset += bcma_host_pci_provide_access_to_core(core);
++	iowrite32(value, core->bus->mmio + offset);
 +}
 +
-+static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr,
-+				  u32 type, u8 port)
++#ifdef CONFIG_BCMA_BLOCKIO
++void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
++			      size_t count, u16 offset, u8 reg_width)
 +{
-+	u32 addrl, addrh, sizel, sizeh = 0;
-+	u32 size;
-+
-+	u32 ent = bcma_erom_get_ent(bus, eromptr);
-+	if ((!(ent & SCAN_ER_VALID)) ||
-+	    ((ent & SCAN_ER_TAGX) != SCAN_ER_TAG_ADDR) ||
-+	    ((ent & SCAN_ADDR_TYPE) != type) ||
-+	    (((ent & SCAN_ADDR_PORT) >> SCAN_ADDR_PORT_SHIFT) != port)) {
-+		bcma_erom_push_ent(eromptr);
-+		return -EINVAL;
++	void __iomem *addr = core->bus->mmio + offset;
++	if (core->bus->mapped_core != core)
++		bcma_host_pci_switch_core(core);
++	switch (reg_width) {
++	case sizeof(u8):
++		ioread8_rep(addr, buffer, count);
++		break;
++	case sizeof(u16):
++		WARN_ON(count & 1);
++		ioread16_rep(addr, buffer, count >> 1);
++		break;
++	case sizeof(u32):
++		WARN_ON(count & 3);
++		ioread32_rep(addr, buffer, count >> 2);
++		break;
++	default:
++		WARN_ON(1);
 +	}
-+
-+	addrl = ent & SCAN_ADDR_ADDR;
-+	if (ent & SCAN_ADDR_AG32)
-+		addrh = bcma_erom_get_ent(bus, eromptr);
-+	else
-+		addrh = 0;
-+
-+	if ((ent & SCAN_ADDR_SZ) == SCAN_ADDR_SZ_SZD) {
-+		size = bcma_erom_get_ent(bus, eromptr);
-+		sizel = size & SCAN_SIZE_SZ;
-+		if (size & SCAN_SIZE_SG32)
-+			sizeh = bcma_erom_get_ent(bus, eromptr);
-+	} else
-+		sizel = SCAN_ADDR_SZ_BASE <<
-+				((ent & SCAN_ADDR_SZ) >> SCAN_ADDR_SZ_SHIFT);
-+
-+	return addrl;
 +}
 +
-+static struct bcma_device *bcma_find_core_by_index(struct bcma_bus *bus,
-+						   u16 index)
++void bcma_host_pci_block_write(struct bcma_device *core, const void *buffer,
++			       size_t count, u16 offset, u8 reg_width)
 +{
-+	struct bcma_device *core;
-+
-+	list_for_each_entry(core, &bus->cores, list) {
-+		if (core->core_index == index)
-+			return core;
++	void __iomem *addr = core->bus->mmio + offset;
++	if (core->bus->mapped_core != core)
++		bcma_host_pci_switch_core(core);
++	switch (reg_width) {
++	case sizeof(u8):
++		iowrite8_rep(addr, buffer, count);
++		break;
++	case sizeof(u16):
++		WARN_ON(count & 1);
++		iowrite16_rep(addr, buffer, count >> 1);
++		break;
++	case sizeof(u32):
++		WARN_ON(count & 3);
++		iowrite32_rep(addr, buffer, count >> 2);
++		break;
++	default:
++		WARN_ON(1);
 +	}
-+	return NULL;
 +}
++#endif
 +
-+static struct bcma_device *bcma_find_core_reverse(struct bcma_bus *bus, u16 coreid)
++static u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset)
 +{
-+	struct bcma_device *core;
++	if (core->bus->mapped_core != core)
++		bcma_host_pci_switch_core(core);
++	return ioread32(core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset);
++}
 +
-+	list_for_each_entry_reverse(core, &bus->cores, list) {
-+		if (core->id.id == coreid)
-+			return core;
-+	}
-+	return NULL;
++static void bcma_host_pci_awrite32(struct bcma_device *core, u16 offset,
++				  u32 value)
++{
++	if (core->bus->mapped_core != core)
++		bcma_host_pci_switch_core(core);
++	iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset);
 +}
 +
-+static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
-+			      struct bcma_device_id *match, int core_num,
-+			      struct bcma_device *core)
++const struct bcma_host_ops bcma_host_pci_ops = {
++	.read8		= bcma_host_pci_read8,
++	.read16		= bcma_host_pci_read16,
++	.read32		= bcma_host_pci_read32,
++	.write8		= bcma_host_pci_write8,
++	.write16	= bcma_host_pci_write16,
++	.write32	= bcma_host_pci_write32,
++#ifdef CONFIG_BCMA_BLOCKIO
++	.block_read	= bcma_host_pci_block_read,
++	.block_write	= bcma_host_pci_block_write,
++#endif
++	.aread32	= bcma_host_pci_aread32,
++	.awrite32	= bcma_host_pci_awrite32,
++};
++
++static int __devinit bcma_host_pci_probe(struct pci_dev *dev,
++					 const struct pci_device_id *id)
 +{
-+	s32 tmp;
-+	u8 i, j;
-+	s32 cia, cib;
-+	u8 ports[2], wrappers[2];
++	struct bcma_bus *bus;
++	int err = -ENOMEM;
++	const char *name;
++	u32 val;
 +
-+	/* get CIs */
-+	cia = bcma_erom_get_ci(bus, eromptr);
-+	if (cia < 0) {
-+		bcma_erom_push_ent(eromptr);
-+		if (bcma_erom_is_end(bus, eromptr))
-+			return -ESPIPE;
-+		return -EILSEQ;
-+	}
-+	cib = bcma_erom_get_ci(bus, eromptr);
-+	if (cib < 0)
-+		return -EILSEQ;
++	/* Alloc */
++	bus = kzalloc(sizeof(*bus), GFP_KERNEL);
++	if (!bus)
++		goto out;
 +
-+	/* parse CIs */
-+	core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
-+	core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
-+	core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT;
-+	ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT;
-+	ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT;
-+	wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT;
-+	wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT;
-+	core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;
++	/* Basic PCI configuration */
++	err = pci_enable_device(dev);
++	if (err)
++		goto err_kfree_bus;
 +
-+	if (((core->id.manuf == BCMA_MANUF_ARM) &&
-+	     (core->id.id == 0xFFF)) ||
-+	    (ports[1] == 0)) {
-+		bcma_erom_skip_component(bus, eromptr);
-+		return -ENXIO;
-+	}
++	name = dev_name(&dev->dev);
++	if (dev->driver && dev->driver->name)
++		name = dev->driver->name;
++	err = pci_request_regions(dev, name);
++	if (err)
++		goto err_pci_disable;
++	pci_set_master(dev);
 +
-+	/* check if component is a core at all */
-+	if (wrappers[0] + wrappers[1] == 0) {
-+		/* we could save addrl of the router
-+		if (cid == BCMA_CORE_OOB_ROUTER)
-+		 */
-+		bcma_erom_skip_component(bus, eromptr);
-+		return -ENXIO;
-+	}
++	/* Disable the RETRY_TIMEOUT register (0x41) to keep
++	 * PCI Tx retries from interfering with C3 CPU state */
++	pci_read_config_dword(dev, 0x40, &val);
++	if ((val & 0x0000ff00) != 0)
++		pci_write_config_dword(dev, 0x40, val & 0xffff00ff);
 +
-+	if (bcma_erom_is_bridge(bus, eromptr)) {
-+		bcma_erom_skip_component(bus, eromptr);
-+		return -ENXIO;
-+	}
++	/* SSB needed additional powering up, do we have any AMBA PCI cards? */
++	if (!pci_is_pcie(dev))
++		pr_err("PCI card detected, report problems.\n");
 +
-+	if (bcma_find_core_by_index(bus, core_num)) {
-+		bcma_erom_skip_component(bus, eromptr);
-+		return -ENODEV;
-+	}
++	/* Map MMIO */
++	err = -ENOMEM;
++	bus->mmio = pci_iomap(dev, 0, ~0UL);
++	if (!bus->mmio)
++		goto err_pci_release_regions;
 +
-+	if (match && ((match->manuf != BCMA_ANY_MANUF &&
-+	      match->manuf != core->id.manuf) ||
-+	     (match->id != BCMA_ANY_ID && match->id != core->id.id) ||
-+	     (match->rev != BCMA_ANY_REV && match->rev != core->id.rev) ||
-+	     (match->class != BCMA_ANY_CLASS && match->class != core->id.class)
-+	    )) {
-+		bcma_erom_skip_component(bus, eromptr);
-+		return -ENODEV;
-+	}
++	/* Host specific */
++	bus->host_pci = dev;
++	bus->hosttype = BCMA_HOSTTYPE_PCI;
++	bus->ops = &bcma_host_pci_ops;
 +
-+	/* get & parse master ports */
-+	for (i = 0; i < ports[0]; i++) {
-+		s32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr);
-+		if (mst_port_d < 0)
-+			return -EILSEQ;
-+	}
++	bus->boardinfo.vendor = bus->host_pci->subsystem_vendor;
++	bus->boardinfo.type = bus->host_pci->subsystem_device;
 +
-+	/* get & parse slave ports */
-+	for (i = 0; i < ports[1]; i++) {
-+		for (j = 0; ; j++) {
-+			tmp = bcma_erom_get_addr_desc(bus, eromptr,
-+				SCAN_ADDR_TYPE_SLAVE, i);
-+			if (tmp < 0) {
-+				/* no more entries for port _i_ */
-+				/* pr_debug("erom: slave port %d "
-+				 * "has %d descriptors\n", i, j); */
-+				break;
-+			} else {
-+				if (i == 0 && j == 0)
-+					core->addr = tmp;
-+			}
-+		}
-+	}
++	/* Register */
++	err = bcma_bus_register(bus);
++	if (err)
++		goto err_pci_unmap_mmio;
 +
-+	/* get & parse master wrappers */
-+	for (i = 0; i < wrappers[0]; i++) {
-+		for (j = 0; ; j++) {
-+			tmp = bcma_erom_get_addr_desc(bus, eromptr,
-+				SCAN_ADDR_TYPE_MWRAP, i);
-+			if (tmp < 0) {
-+				/* no more entries for port _i_ */
-+				/* pr_debug("erom: master wrapper %d "
-+				 * "has %d descriptors\n", i, j); */
-+				break;
-+			} else {
-+				if (i == 0 && j == 0)
-+					core->wrap = tmp;
-+			}
-+		}
-+	}
++	pci_set_drvdata(dev, bus);
 +
-+	/* get & parse slave wrappers */
-+	for (i = 0; i < wrappers[1]; i++) {
-+		u8 hack = (ports[1] == 1) ? 0 : 1;
-+		for (j = 0; ; j++) {
-+			tmp = bcma_erom_get_addr_desc(bus, eromptr,
-+				SCAN_ADDR_TYPE_SWRAP, i + hack);
-+			if (tmp < 0) {
-+				/* no more entries for port _i_ */
-+				/* pr_debug("erom: master wrapper %d "
-+				 * has %d descriptors\n", i, j); */
-+				break;
-+			} else {
-+				if (wrappers[0] == 0 && !i && !j)
-+					core->wrap = tmp;
-+			}
-+		}
-+	}
-+	if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
-+		core->io_addr = ioremap_nocache(core->addr, BCMA_CORE_SIZE);
-+		if (!core->io_addr)
-+			return -ENOMEM;
-+		core->io_wrap = ioremap_nocache(core->wrap, BCMA_CORE_SIZE);
-+		if (!core->io_wrap) {
-+			iounmap(core->io_addr);
-+			return -ENOMEM;
-+		}
-+	}
-+	return 0;
++out:
++	return err;
++
++err_pci_unmap_mmio:
++	pci_iounmap(dev, bus->mmio);
++err_pci_release_regions:
++	pci_release_regions(dev);
++err_pci_disable:
++	pci_disable_device(dev);
++err_kfree_bus:
++	kfree(bus);
++	return err;
 +}
 +
-+void bcma_init_bus(struct bcma_bus *bus)
++static void __devexit bcma_host_pci_remove(struct pci_dev *dev)
 +{
-+	s32 tmp;
-+	struct bcma_chipinfo *chipinfo = &(bus->chipinfo);
++	struct bcma_bus *bus = pci_get_drvdata(dev);
 +
-+	if (bus->init_done)
-+		return;
++	bcma_bus_unregister(bus);
++	pci_iounmap(dev, bus->mmio);
++	pci_release_regions(dev);
++	pci_disable_device(dev);
++	kfree(bus);
++	pci_set_drvdata(dev, NULL);
++}
 +
-+	INIT_LIST_HEAD(&bus->cores);
-+	bus->nr_cores = 0;
++#ifdef CONFIG_PM
++static int bcma_host_pci_suspend(struct device *dev)
++{
++	struct pci_dev *pdev = to_pci_dev(dev);
++	struct bcma_bus *bus = pci_get_drvdata(pdev);
 +
-+	bcma_scan_switch_core(bus, BCMA_ADDR_BASE);
++	bus->mapped_core = NULL;
 +
-+	tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID);
-+	chipinfo->id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
-+	chipinfo->rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
-+	chipinfo->pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
-+	pr_info("Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n",
-+		chipinfo->id, chipinfo->rev, chipinfo->pkg);
-+
-+	bus->init_done = true;
++	return bcma_bus_suspend(bus);
 +}
 +
-+int bcma_bus_scan(struct bcma_bus *bus)
++static int bcma_host_pci_resume(struct device *dev)
 +{
-+	u32 erombase;
-+	u32 __iomem *eromptr, *eromend;
-+
-+	int err, core_num = 0;
++	struct pci_dev *pdev = to_pci_dev(dev);
++	struct bcma_bus *bus = pci_get_drvdata(pdev);
 +
-+	bcma_init_bus(bus);
++	return bcma_bus_resume(bus);
++}
 +
-+	erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
-+	if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
-+		eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
-+		if (!eromptr)
-+			return -ENOMEM;
-+	} else {
-+		eromptr = bus->mmio;
-+	}
++static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend,
++			 bcma_host_pci_resume);
++#define BCMA_PM_OPS	(&bcma_pm_ops)
 +
-+	eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
++#else /* CONFIG_PM */
 +
-+	bcma_scan_switch_core(bus, erombase);
++#define BCMA_PM_OPS     NULL
 +
-+	while (eromptr < eromend) {
-+		struct bcma_device *other_core;
-+		struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL);
-+		if (!core)
-+			return -ENOMEM;
-+		INIT_LIST_HEAD(&core->list);
-+		core->bus = bus;
++#endif /* CONFIG_PM */
 +
-+		err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core);
-+		if (err < 0) {
-+			kfree(core);
-+			if (err == -ENODEV) {
-+				core_num++;
-+				continue;
-+			} else if (err == -ENXIO) {
-+				continue;
-+			} else if (err == -ESPIPE) {
-+				break;
-+			}
-+			return err;
-+		}
++static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
++	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
++	{ 0, },
++};
++MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl);
 +
-+		core->core_index = core_num++;
-+		bus->nr_cores++;
-+		other_core = bcma_find_core_reverse(bus, core->id.id);
-+		core->core_unit = (other_core == NULL) ? 0 : other_core->core_unit + 1;
++static struct pci_driver bcma_pci_bridge_driver = {
++	.name = "bcma-pci-bridge",
++	.id_table = bcma_pci_bridge_tbl,
++	.probe = bcma_host_pci_probe,
++	.remove = __devexit_p(bcma_host_pci_remove),
++	.driver.pm = BCMA_PM_OPS,
++};
 +
-+		pr_info("Core %d found: %s "
-+			"(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
-+			core->core_index, bcma_device_name(&core->id),
-+			core->id.manuf, core->id.id, core->id.rev,
-+			core->id.class);
++int __init bcma_host_pci_init(void)
++{
++	return pci_register_driver(&bcma_pci_bridge_driver);
++}
 +
-+		list_add(&core->list, &bus->cores);
-+	}
++void __exit bcma_host_pci_exit(void)
++{
++	pci_unregister_driver(&bcma_pci_bridge_driver);
++}
+--- /dev/null
++++ b/drivers/bcma/host_soc.c
+@@ -0,0 +1,183 @@
++/*
++ * Broadcom specific AMBA
++ * System on Chip (SoC) Host
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
 +
-+	if (bus->hosttype == BCMA_HOSTTYPE_SOC)
-+		iounmap(eromptr);
++#include "bcma_private.h"
++#include "scan.h"
++#include <linux/bcma/bcma.h>
++#include <linux/bcma/bcma_soc.h>
 +
-+	return 0;
++static u8 bcma_host_soc_read8(struct bcma_device *core, u16 offset)
++{
++	return readb(core->io_addr + offset);
 +}
 +
-+int __init bcma_bus_scan_early(struct bcma_bus *bus,
-+			       struct bcma_device_id *match,
-+			       struct bcma_device *core)
++static u16 bcma_host_soc_read16(struct bcma_device *core, u16 offset)
 +{
-+	u32 erombase;
-+	u32 __iomem *eromptr, *eromend;
-+
-+	int err = -ENODEV;
-+	int core_num = 0;
++	return readw(core->io_addr + offset);
++}
 +
-+	erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
-+	if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
-+		eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
-+		if (!eromptr)
-+			return -ENOMEM;
-+	} else {
-+		eromptr = bus->mmio;
-+	}
++static u32 bcma_host_soc_read32(struct bcma_device *core, u16 offset)
++{
++	return readl(core->io_addr + offset);
++}
 +
-+	eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
++static void bcma_host_soc_write8(struct bcma_device *core, u16 offset,
++				 u8 value)
++{
++	writeb(value, core->io_addr + offset);
++}
 +
-+	bcma_scan_switch_core(bus, erombase);
++static void bcma_host_soc_write16(struct bcma_device *core, u16 offset,
++				 u16 value)
++{
++	writew(value, core->io_addr + offset);
++}
 +
-+	while (eromptr < eromend) {
-+		memset(core, 0, sizeof(*core));
-+		INIT_LIST_HEAD(&core->list);
-+		core->bus = bus;
++static void bcma_host_soc_write32(struct bcma_device *core, u16 offset,
++				 u32 value)
++{
++	writel(value, core->io_addr + offset);
++}
 +
-+		err = bcma_get_next_core(bus, &eromptr, match, core_num, core);
-+		if (err == -ENODEV) {
-+			core_num++;
-+			continue;
-+		} else if (err == -ENXIO)
-+			continue;
-+		else if (err == -ESPIPE)
-+			break;
-+		else if (err < 0)
-+			return err;
++#ifdef CONFIG_BCMA_BLOCKIO
++static void bcma_host_soc_block_read(struct bcma_device *core, void *buffer,
++				     size_t count, u16 offset, u8 reg_width)
++{
++	void __iomem *addr = core->io_addr + offset;
 +
-+		core->core_index = core_num++;
-+		bus->nr_cores++;
-+		pr_info("Core %d found: %s "
-+			"(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
-+			core->core_index, bcma_device_name(&core->id),
-+			core->id.manuf, core->id.id, core->id.rev,
-+			core->id.class);
++	switch (reg_width) {
++	case sizeof(u8): {
++		u8 *buf = buffer;
 +
-+		list_add(&core->list, &bus->cores);
-+		err = 0;
++		while (count) {
++			*buf = __raw_readb(addr);
++			buf++;
++			count--;
++		}
 +		break;
 +	}
++	case sizeof(u16): {
++		__le16 *buf = buffer;
 +
-+	if (bus->hosttype == BCMA_HOSTTYPE_SOC)
-+		iounmap(eromptr);
++		WARN_ON(count & 1);
++		while (count) {
++			*buf = (__force __le16)__raw_readw(addr);
++			buf++;
++			count -= 2;
++		}
++		break;
++	}
++	case sizeof(u32): {
++		__le32 *buf = buffer;
 +
-+	return err;
++		WARN_ON(count & 3);
++		while (count) {
++			*buf = (__force __le32)__raw_readl(addr);
++			buf++;
++			count -= 4;
++		}
++		break;
++	}
++	default:
++		WARN_ON(1);
++	}
 +}
---- /dev/null
-+++ b/drivers/bcma/scan.h
-@@ -0,0 +1,56 @@
-+#ifndef BCMA_SCAN_H_
-+#define BCMA_SCAN_H_
 +
-+#define BCMA_ADDR_BASE		0x18000000
-+#define BCMA_WRAP_BASE		0x18100000
++static void bcma_host_soc_block_write(struct bcma_device *core,
++				      const void *buffer,
++				      size_t count, u16 offset, u8 reg_width)
++{
++	void __iomem *addr = core->io_addr + offset;
 +
-+#define SCAN_ER_VALID		0x00000001
-+#define SCAN_ER_TAGX		0x00000006 /* we have to ignore 0x8 bit when checking tag for SCAN_ER_TAG_ADDR */
-+#define SCAN_ER_TAG		0x0000000E
-+#define  SCAN_ER_TAG_CI		0x00000000
-+#define  SCAN_ER_TAG_MP		0x00000002
-+#define  SCAN_ER_TAG_ADDR	0x00000004
-+#define  SCAN_ER_TAG_END	0x0000000E
-+#define SCAN_ER_BAD		0xFFFFFFFF
++	switch (reg_width) {
++	case sizeof(u8): {
++		const u8 *buf = buffer;
 +
-+#define SCAN_CIA_CLASS		0x000000F0
-+#define SCAN_CIA_CLASS_SHIFT	4
-+#define SCAN_CIA_ID		0x000FFF00
-+#define SCAN_CIA_ID_SHIFT	8
-+#define SCAN_CIA_MANUF		0xFFF00000
-+#define SCAN_CIA_MANUF_SHIFT	20
++		while (count) {
++			__raw_writeb(*buf, addr);
++			buf++;
++			count--;
++		}
++		break;
++	}
++	case sizeof(u16): {
++		const __le16 *buf = buffer;
 +
-+#define SCAN_CIB_NMP		0x000001F0
-+#define SCAN_CIB_NMP_SHIFT	4
-+#define SCAN_CIB_NSP		0x00003E00
-+#define SCAN_CIB_NSP_SHIFT	9
-+#define SCAN_CIB_NMW		0x0007C000
-+#define SCAN_CIB_NMW_SHIFT	14
-+#define SCAN_CIB_NSW		0x00F80000
-+#define SCAN_CIB_NSW_SHIFT	17
-+#define SCAN_CIB_REV		0xFF000000
-+#define SCAN_CIB_REV_SHIFT	24
-+
-+#define SCAN_ADDR_AG32		0x00000008
-+#define SCAN_ADDR_SZ		0x00000030
-+#define SCAN_ADDR_SZ_SHIFT	4
-+#define  SCAN_ADDR_SZ_4K	0x00000000
-+#define  SCAN_ADDR_SZ_8K	0x00000010
-+#define  SCAN_ADDR_SZ_16K	0x00000020
-+#define  SCAN_ADDR_SZ_SZD	0x00000030
-+#define SCAN_ADDR_TYPE		0x000000C0
-+#define  SCAN_ADDR_TYPE_SLAVE	0x00000000
-+#define  SCAN_ADDR_TYPE_BRIDGE	0x00000040
-+#define  SCAN_ADDR_TYPE_SWRAP	0x00000080
-+#define  SCAN_ADDR_TYPE_MWRAP	0x000000C0
-+#define SCAN_ADDR_PORT		0x00000F00
-+#define SCAN_ADDR_PORT_SHIFT	8
-+#define SCAN_ADDR_ADDR		0xFFFFF000
-+
-+#define SCAN_ADDR_SZ_BASE	0x00001000	/* 4KB */
-+
-+#define SCAN_SIZE_SZ_ALIGN	0x00000FFF
-+#define SCAN_SIZE_SZ		0xFFFFF000
-+#define SCAN_SIZE_SG32		0x00000008
-+
-+#endif /* BCMA_SCAN_H_ */
---- /dev/null
-+++ b/include/linux/bcma/bcma.h
-@@ -0,0 +1,307 @@
-+#ifndef LINUX_BCMA_H_
-+#define LINUX_BCMA_H_
-+
-+#include <linux/pci.h>
-+#include <linux/mod_devicetable.h>
-+
-+#include <linux/bcma/bcma_driver_chipcommon.h>
-+#include <linux/bcma/bcma_driver_pci.h>
-+#include <linux/bcma/bcma_driver_mips.h>
-+#include <linux/ssb/ssb.h> /* SPROM sharing */
-+
-+#include "bcma_regs.h"
-+
-+struct bcma_device;
-+struct bcma_bus;
++		WARN_ON(count & 1);
++		while (count) {
++			__raw_writew((__force u16)(*buf), addr);
++			buf++;
++			count -= 2;
++		}
++		break;
++	}
++	case sizeof(u32): {
++		const __le32 *buf = buffer;
 +
-+enum bcma_hosttype {
-+	BCMA_HOSTTYPE_PCI,
-+	BCMA_HOSTTYPE_SDIO,
-+	BCMA_HOSTTYPE_SOC,
-+};
++		WARN_ON(count & 3);
++		while (count) {
++			__raw_writel((__force u32)(*buf), addr);
++			buf++;
++			count -= 4;
++		}
++		break;
++	}
++	default:
++		WARN_ON(1);
++	}
++}
++#endif /* CONFIG_BCMA_BLOCKIO */
 +
-+struct bcma_chipinfo {
-+	u16 id;
-+	u8 rev;
-+	u8 pkg;
-+};
++static u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset)
++{
++	return readl(core->io_wrap + offset);
++}
 +
-+enum bcma_clkmode {
-+	BCMA_CLKMODE_FAST,
-+	BCMA_CLKMODE_DYNAMIC,
-+};
++static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
++				  u32 value)
++{
++	writel(value, core->io_wrap + offset);
++}
 +
-+struct bcma_host_ops {
-+	u8 (*read8)(struct bcma_device *core, u16 offset);
-+	u16 (*read16)(struct bcma_device *core, u16 offset);
-+	u32 (*read32)(struct bcma_device *core, u16 offset);
-+	void (*write8)(struct bcma_device *core, u16 offset, u8 value);
-+	void (*write16)(struct bcma_device *core, u16 offset, u16 value);
-+	void (*write32)(struct bcma_device *core, u16 offset, u32 value);
++const struct bcma_host_ops bcma_host_soc_ops = {
++	.read8		= bcma_host_soc_read8,
++	.read16		= bcma_host_soc_read16,
++	.read32		= bcma_host_soc_read32,
++	.write8		= bcma_host_soc_write8,
++	.write16	= bcma_host_soc_write16,
++	.write32	= bcma_host_soc_write32,
 +#ifdef CONFIG_BCMA_BLOCKIO
-+	void (*block_read)(struct bcma_device *core, void *buffer,
-+			   size_t count, u16 offset, u8 reg_width);
-+	void (*block_write)(struct bcma_device *core, const void *buffer,
-+			    size_t count, u16 offset, u8 reg_width);
++	.block_read	= bcma_host_soc_block_read,
++	.block_write	= bcma_host_soc_block_write,
 +#endif
-+	/* Agent ops */
-+	u32 (*aread32)(struct bcma_device *core, u16 offset);
-+	void (*awrite32)(struct bcma_device *core, u16 offset, u32 value);
++	.aread32	= bcma_host_soc_aread32,
++	.awrite32	= bcma_host_soc_awrite32,
 +};
 +
-+/* Core manufacturers */
-+#define BCMA_MANUF_ARM			0x43B
-+#define BCMA_MANUF_MIPS			0x4A7
-+#define BCMA_MANUF_BCM			0x4BF
-+
-+/* Core class values. */
-+#define BCMA_CL_SIM			0x0
-+#define BCMA_CL_EROM			0x1
-+#define BCMA_CL_CORESIGHT		0x9
-+#define BCMA_CL_VERIF			0xB
-+#define BCMA_CL_OPTIMO			0xD
-+#define BCMA_CL_GEN			0xE
-+#define BCMA_CL_PRIMECELL		0xF
++int __init bcma_host_soc_register(struct bcma_soc *soc)
++{
++	struct bcma_bus *bus = &soc->bus;
++	int err;
 +
-+/* Core-ID values. */
-+#define BCMA_CORE_OOB_ROUTER		0x367	/* Out of band */
-+#define BCMA_CORE_INVALID		0x700
-+#define BCMA_CORE_CHIPCOMMON		0x800
-+#define BCMA_CORE_ILINE20		0x801
-+#define BCMA_CORE_SRAM			0x802
-+#define BCMA_CORE_SDRAM			0x803
-+#define BCMA_CORE_PCI			0x804
-+#define BCMA_CORE_MIPS			0x805
-+#define BCMA_CORE_ETHERNET		0x806
-+#define BCMA_CORE_V90			0x807
-+#define BCMA_CORE_USB11_HOSTDEV		0x808
-+#define BCMA_CORE_ADSL			0x809
-+#define BCMA_CORE_ILINE100		0x80A
-+#define BCMA_CORE_IPSEC			0x80B
-+#define BCMA_CORE_UTOPIA		0x80C
-+#define BCMA_CORE_PCMCIA		0x80D
-+#define BCMA_CORE_INTERNAL_MEM		0x80E
-+#define BCMA_CORE_MEMC_SDRAM		0x80F
-+#define BCMA_CORE_OFDM			0x810
-+#define BCMA_CORE_EXTIF			0x811
-+#define BCMA_CORE_80211			0x812
-+#define BCMA_CORE_PHY_A			0x813
-+#define BCMA_CORE_PHY_B			0x814
-+#define BCMA_CORE_PHY_G			0x815
-+#define BCMA_CORE_MIPS_3302		0x816
-+#define BCMA_CORE_USB11_HOST		0x817
-+#define BCMA_CORE_USB11_DEV		0x818
-+#define BCMA_CORE_USB20_HOST		0x819
-+#define BCMA_CORE_USB20_DEV		0x81A
-+#define BCMA_CORE_SDIO_HOST		0x81B
-+#define BCMA_CORE_ROBOSWITCH		0x81C
-+#define BCMA_CORE_PARA_ATA		0x81D
-+#define BCMA_CORE_SATA_XORDMA		0x81E
-+#define BCMA_CORE_ETHERNET_GBIT		0x81F
-+#define BCMA_CORE_PCIE			0x820
-+#define BCMA_CORE_PHY_N			0x821
-+#define BCMA_CORE_SRAM_CTL		0x822
-+#define BCMA_CORE_MINI_MACPHY		0x823
-+#define BCMA_CORE_ARM_1176		0x824
-+#define BCMA_CORE_ARM_7TDMI		0x825
-+#define BCMA_CORE_PHY_LP		0x826
-+#define BCMA_CORE_PMU			0x827
-+#define BCMA_CORE_PHY_SSN		0x828
-+#define BCMA_CORE_SDIO_DEV		0x829
-+#define BCMA_CORE_ARM_CM3		0x82A
-+#define BCMA_CORE_PHY_HT		0x82B
-+#define BCMA_CORE_MIPS_74K		0x82C
-+#define BCMA_CORE_MAC_GBIT		0x82D
-+#define BCMA_CORE_DDR12_MEM_CTL		0x82E
-+#define BCMA_CORE_PCIE_RC		0x82F	/* PCIe Root Complex */
-+#define BCMA_CORE_OCP_OCP_BRIDGE	0x830
-+#define BCMA_CORE_SHARED_COMMON		0x831
-+#define BCMA_CORE_OCP_AHB_BRIDGE	0x832
-+#define BCMA_CORE_SPI_HOST		0x833
-+#define BCMA_CORE_I2S			0x834
-+#define BCMA_CORE_SDR_DDR1_MEM_CTL	0x835	/* SDR/DDR1 memory controller core */
-+#define BCMA_CORE_SHIM			0x837	/* SHIM component in ubus/6362 */
-+#define BCMA_CORE_DEFAULT		0xFFF
++	/* iomap only first core. We have to read some register on this core
++	 * to scan the bus.
++	 */
++	bus->mmio = ioremap_nocache(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
++	if (!bus->mmio)
++		return -ENOMEM;
 +
-+#define BCMA_MAX_NR_CORES		16
++	/* Host specific */
++	bus->hosttype = BCMA_HOSTTYPE_SOC;
++	bus->ops = &bcma_host_soc_ops;
 +
-+struct bcma_device {
-+	struct bcma_bus *bus;
-+	struct bcma_device_id id;
++	/* Register */
++	err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips);
++	if (err)
++		iounmap(bus->mmio);
 +
-+	struct device dev;
-+	struct device *dma_dev;
++	return err;
++}
+--- /dev/null
++++ b/drivers/bcma/main.c
+@@ -0,0 +1,387 @@
++/*
++ * Broadcom specific AMBA
++ * Bus subsystem
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
 +
-+	unsigned int irq;
-+	bool dev_registered;
++#include "bcma_private.h"
++#include <linux/module.h>
++#include <linux/bcma/bcma.h>
++#include <linux/slab.h>
 +
-+	u8 core_index;
-+	u8 core_unit;
++MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
++MODULE_LICENSE("GPL");
 +
-+	u32 addr;
-+	u32 wrap;
++/* contains the number the next bus should get. */
++static unsigned int bcma_bus_next_num = 0;
 +
-+	void __iomem *io_addr;
-+	void __iomem *io_wrap;
++/* bcma_buses_mutex locks the bcma_bus_next_num */
++static DEFINE_MUTEX(bcma_buses_mutex);
 +
-+	void *drvdata;
-+	struct list_head list;
-+};
++static int bcma_bus_match(struct device *dev, struct device_driver *drv);
++static int bcma_device_probe(struct device *dev);
++static int bcma_device_remove(struct device *dev);
++static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env);
 +
-+static inline void *bcma_get_drvdata(struct bcma_device *core)
++static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf)
 +{
-+	return core->drvdata;
++	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
++	return sprintf(buf, "0x%03X\n", core->id.manuf);
 +}
-+static inline void bcma_set_drvdata(struct bcma_device *core, void *drvdata)
++static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf)
 +{
-+	core->drvdata = drvdata;
++	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
++	return sprintf(buf, "0x%03X\n", core->id.id);
 +}
++static ssize_t rev_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
++	return sprintf(buf, "0x%02X\n", core->id.rev);
++}
++static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
++	return sprintf(buf, "0x%X\n", core->id.class);
++}
++static struct device_attribute bcma_device_attrs[] = {
++	__ATTR_RO(manuf),
++	__ATTR_RO(id),
++	__ATTR_RO(rev),
++	__ATTR_RO(class),
++	__ATTR_NULL,
++};
 +
-+struct bcma_driver {
-+	const char *name;
-+	const struct bcma_device_id *id_table;
-+
-+	int (*probe)(struct bcma_device *dev);
-+	void (*remove)(struct bcma_device *dev);
-+	int (*suspend)(struct bcma_device *dev);
-+	int (*resume)(struct bcma_device *dev);
-+	void (*shutdown)(struct bcma_device *dev);
-+
-+	struct device_driver drv;
++static struct bus_type bcma_bus_type = {
++	.name		= "bcma",
++	.match		= bcma_bus_match,
++	.probe		= bcma_device_probe,
++	.remove		= bcma_device_remove,
++	.uevent		= bcma_device_uevent,
++	.dev_attrs	= bcma_device_attrs,
 +};
-+extern
-+int __bcma_driver_register(struct bcma_driver *drv, struct module *owner);
-+#define bcma_driver_register(drv) \
-+	__bcma_driver_register(drv, THIS_MODULE)
 +
-+extern void bcma_driver_unregister(struct bcma_driver *drv);
++struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
++{
++	struct bcma_device *core;
 +
-+/* Set a fallback SPROM.
-+ * See kdoc at the function definition for complete documentation. */
-+extern int bcma_arch_register_fallback_sprom(
-+		int (*sprom_callback)(struct bcma_bus *bus,
-+		struct ssb_sprom *out));
++	list_for_each_entry(core, &bus->cores, list) {
++		if (core->id.id == coreid)
++			return core;
++	}
++	return NULL;
++}
++EXPORT_SYMBOL_GPL(bcma_find_core);
 +
-+struct bcma_bus {
-+	/* The MMIO area. */
-+	void __iomem *mmio;
++static void bcma_release_core_dev(struct device *dev)
++{
++	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
++	if (core->io_addr)
++		iounmap(core->io_addr);
++	if (core->io_wrap)
++		iounmap(core->io_wrap);
++	kfree(core);
++}
 +
-+	const struct bcma_host_ops *ops;
++static int bcma_register_cores(struct bcma_bus *bus)
++{
++	struct bcma_device *core;
++	int err, dev_id = 0;
 +
-+	enum bcma_hosttype hosttype;
-+	union {
-+		/* Pointer to the PCI bus (only for BCMA_HOSTTYPE_PCI) */
-+		struct pci_dev *host_pci;
-+		/* Pointer to the SDIO device (only for BCMA_HOSTTYPE_SDIO) */
-+		struct sdio_func *host_sdio;
-+	};
++	list_for_each_entry(core, &bus->cores, list) {
++		/* We support that cores ourself */
++		switch (core->id.id) {
++		case BCMA_CORE_CHIPCOMMON:
++		case BCMA_CORE_PCI:
++		case BCMA_CORE_PCIE:
++		case BCMA_CORE_MIPS_74K:
++			continue;
++		}
 +
-+	struct bcma_chipinfo chipinfo;
++		core->dev.release = bcma_release_core_dev;
++		core->dev.bus = &bcma_bus_type;
++		dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id);
 +
-+	struct bcma_device *mapped_core;
-+	struct list_head cores;
-+	u8 nr_cores;
-+	u8 init_done:1;
-+	u8 num;
++		switch (bus->hosttype) {
++		case BCMA_HOSTTYPE_PCI:
++			core->dev.parent = &bus->host_pci->dev;
++			core->dma_dev = &bus->host_pci->dev;
++			core->irq = bus->host_pci->irq;
++			break;
++		case BCMA_HOSTTYPE_SOC:
++			core->dev.dma_mask = &core->dev.coherent_dma_mask;
++			core->dma_dev = &core->dev;
++			break;
++		case BCMA_HOSTTYPE_SDIO:
++			break;
++		}
 +
-+	struct bcma_drv_cc drv_cc;
-+	struct bcma_drv_pci drv_pci;
-+	struct bcma_drv_mips drv_mips;
++		err = device_register(&core->dev);
++		if (err) {
++			pr_err("Could not register dev for core 0x%03X\n",
++			       core->id.id);
++			continue;
++		}
++		core->dev_registered = true;
++		dev_id++;
++	}
 +
-+	/* We decided to share SPROM struct with SSB as long as we do not need
-+	 * any hacks for BCMA. This simplifies drivers code. */
-+	struct ssb_sprom sprom;
-+};
++	return 0;
++}
 +
-+static inline u32 bcma_read8(struct bcma_device *core, u16 offset)
++static void bcma_unregister_cores(struct bcma_bus *bus)
 +{
-+	return core->bus->ops->read8(core, offset);
++	struct bcma_device *core;
++
++	list_for_each_entry(core, &bus->cores, list) {
++		if (core->dev_registered)
++			device_unregister(&core->dev);
++	}
 +}
-+static inline u32 bcma_read16(struct bcma_device *core, u16 offset)
++
++int __devinit bcma_bus_register(struct bcma_bus *bus)
 +{
-+	return core->bus->ops->read16(core, offset);
++	int err;
++	struct bcma_device *core;
++
++	mutex_lock(&bcma_buses_mutex);
++	bus->num = bcma_bus_next_num++;
++	mutex_unlock(&bcma_buses_mutex);
++
++	/* Scan for devices (cores) */
++	err = bcma_bus_scan(bus);
++	if (err) {
++		pr_err("Failed to scan: %d\n", err);
++		return -1;
++	}
++
++	/* Init CC core */
++	core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
++	if (core) {
++		bus->drv_cc.core = core;
++		bcma_core_chipcommon_init(&bus->drv_cc);
++	}
++
++	/* Init MIPS core */
++	core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
++	if (core) {
++		bus->drv_mips.core = core;
++		bcma_core_mips_init(&bus->drv_mips);
++	}
++
++	/* Init PCIE core */
++	core = bcma_find_core(bus, BCMA_CORE_PCIE);
++	if (core) {
++		bus->drv_pci.core = core;
++		bcma_core_pci_init(&bus->drv_pci);
++	}
++
++	/* Try to get SPROM */
++	err = bcma_sprom_get(bus);
++	if (err == -ENOENT) {
++		pr_err("No SPROM available\n");
++	} else if (err)
++		pr_err("Failed to get SPROM: %d\n", err);
++
++	/* Register found cores */
++	bcma_register_cores(bus);
++
++	pr_info("Bus registered\n");
++
++	return 0;
 +}
-+static inline u32 bcma_read32(struct bcma_device *core, u16 offset)
++
++void bcma_bus_unregister(struct bcma_bus *bus)
 +{
-+	return core->bus->ops->read32(core, offset);
++	bcma_unregister_cores(bus);
 +}
-+static inline
-+void bcma_write8(struct bcma_device *core, u16 offset, u32 value)
++
++int __init bcma_bus_early_register(struct bcma_bus *bus,
++				   struct bcma_device *core_cc,
++				   struct bcma_device *core_mips)
 +{
-+	core->bus->ops->write8(core, offset, value);
++	int err;
++	struct bcma_device *core;
++	struct bcma_device_id match;
++
++	bcma_init_bus(bus);
++
++	match.manuf = BCMA_MANUF_BCM;
++	match.id = BCMA_CORE_CHIPCOMMON;
++	match.class = BCMA_CL_SIM;
++	match.rev = BCMA_ANY_REV;
++
++	/* Scan for chip common core */
++	err = bcma_bus_scan_early(bus, &match, core_cc);
++	if (err) {
++		pr_err("Failed to scan for common core: %d\n", err);
++		return -1;
++	}
++
++	match.manuf = BCMA_MANUF_MIPS;
++	match.id = BCMA_CORE_MIPS_74K;
++	match.class = BCMA_CL_SIM;
++	match.rev = BCMA_ANY_REV;
++
++	/* Scan for mips core */
++	err = bcma_bus_scan_early(bus, &match, core_mips);
++	if (err) {
++		pr_err("Failed to scan for mips core: %d\n", err);
++		return -1;
++	}
++
++	/* Init CC core */
++	core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
++	if (core) {
++		bus->drv_cc.core = core;
++		bcma_core_chipcommon_init(&bus->drv_cc);
++	}
++
++	/* Init MIPS core */
++	core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
++	if (core) {
++		bus->drv_mips.core = core;
++		bcma_core_mips_init(&bus->drv_mips);
++	}
++
++	pr_info("Early bus registered\n");
++
++	return 0;
 +}
-+static inline
-+void bcma_write16(struct bcma_device *core, u16 offset, u32 value)
++
++#ifdef CONFIG_PM
++int bcma_bus_suspend(struct bcma_bus *bus)
 +{
-+	core->bus->ops->write16(core, offset, value);
-+}
-+static inline
-+void bcma_write32(struct bcma_device *core, u16 offset, u32 value)
-+{
-+	core->bus->ops->write32(core, offset, value);
-+}
-+#ifdef CONFIG_BCMA_BLOCKIO
-+static inline void bcma_block_read(struct bcma_device *core, void *buffer,
-+				   size_t count, u16 offset, u8 reg_width)
-+{
-+	core->bus->ops->block_read(core, buffer, count, offset, reg_width);
++	struct bcma_device *core;
++
++	list_for_each_entry(core, &bus->cores, list) {
++		struct device_driver *drv = core->dev.driver;
++		if (drv) {
++			struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
++			if (adrv->suspend)
++				adrv->suspend(core);
++		}
++	}
++	return 0;
 +}
-+static inline void bcma_block_write(struct bcma_device *core,
-+				    const void *buffer, size_t count,
-+				    u16 offset, u8 reg_width)
++
++int bcma_bus_resume(struct bcma_bus *bus)
 +{
-+	core->bus->ops->block_write(core, buffer, count, offset, reg_width);
++	struct bcma_device *core;
++
++	/* Init CC core */
++	core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
++	if (core) {
++		bus->drv_cc.setup_done = false;
++		bcma_core_chipcommon_init(&bus->drv_cc);
++	}
++
++	list_for_each_entry(core, &bus->cores, list) {
++		struct device_driver *drv = core->dev.driver;
++		if (drv) {
++			struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
++			if (adrv->resume)
++				adrv->resume(core);
++		}
++	}
++
++	return 0;
 +}
 +#endif
-+static inline u32 bcma_aread32(struct bcma_device *core, u16 offset)
++
++int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
 +{
-+	return core->bus->ops->aread32(core, offset);
++	drv->drv.name = drv->name;
++	drv->drv.bus = &bcma_bus_type;
++	drv->drv.owner = owner;
++
++	return driver_register(&drv->drv);
 +}
-+static inline
-+void bcma_awrite32(struct bcma_device *core, u16 offset, u32 value)
++EXPORT_SYMBOL_GPL(__bcma_driver_register);
++
++void bcma_driver_unregister(struct bcma_driver *drv)
 +{
-+	core->bus->ops->awrite32(core, offset, value);
++	driver_unregister(&drv->drv);
 +}
++EXPORT_SYMBOL_GPL(bcma_driver_unregister);
 +
-+static inline void bcma_mask32(struct bcma_device *cc, u16 offset, u32 mask)
++static int bcma_bus_match(struct device *dev, struct device_driver *drv)
 +{
-+	bcma_write32(cc, offset, bcma_read32(cc, offset) & mask);
++	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
++	struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
++	const struct bcma_device_id *cid = &core->id;
++	const struct bcma_device_id *did;
++
++	for (did = adrv->id_table; did->manuf || did->id || did->rev; did++) {
++	    if ((did->manuf == cid->manuf || did->manuf == BCMA_ANY_MANUF) &&
++		(did->id == cid->id || did->id == BCMA_ANY_ID) &&
++		(did->rev == cid->rev || did->rev == BCMA_ANY_REV) &&
++		(did->class == cid->class || did->class == BCMA_ANY_CLASS))
++			return 1;
++	}
++	return 0;
 +}
-+static inline void bcma_set32(struct bcma_device *cc, u16 offset, u32 set)
++
++static int bcma_device_probe(struct device *dev)
 +{
-+	bcma_write32(cc, offset, bcma_read32(cc, offset) | set);
++	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
++	struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
++					       drv);
++	int err = 0;
++
++	if (adrv->probe)
++		err = adrv->probe(core);
++
++	return err;
 +}
-+static inline void bcma_maskset32(struct bcma_device *cc,
-+				  u16 offset, u32 mask, u32 set)
++
++static int bcma_device_remove(struct device *dev)
 +{
-+	bcma_write32(cc, offset, (bcma_read32(cc, offset) & mask) | set);
++	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
++	struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
++					       drv);
++
++	if (adrv->remove)
++		adrv->remove(core);
++
++	return 0;
 +}
-+static inline void bcma_mask16(struct bcma_device *cc, u16 offset, u16 mask)
++
++static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env)
 +{
-+	bcma_write16(cc, offset, bcma_read16(cc, offset) & mask);
++	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
++
++	return add_uevent_var(env,
++			      "MODALIAS=bcma:m%04Xid%04Xrev%02Xcl%02X",
++			      core->id.manuf, core->id.id,
++			      core->id.rev, core->id.class);
 +}
-+static inline void bcma_set16(struct bcma_device *cc, u16 offset, u16 set)
++
++static int __init bcma_modinit(void)
 +{
-+	bcma_write16(cc, offset, bcma_read16(cc, offset) | set);
++	int err;
++
++	err = bus_register(&bcma_bus_type);
++	if (err)
++		return err;
++
++#ifdef CONFIG_BCMA_HOST_PCI
++	err = bcma_host_pci_init();
++	if (err) {
++		pr_err("PCI host initialization failed\n");
++		err = 0;
++	}
++#endif
++
++	return err;
 +}
-+static inline void bcma_maskset16(struct bcma_device *cc,
-+				  u16 offset, u16 mask, u16 set)
++fs_initcall(bcma_modinit);
++
++static void __exit bcma_modexit(void)
 +{
-+	bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set);
++#ifdef CONFIG_BCMA_HOST_PCI
++	bcma_host_pci_exit();
++#endif
++	bus_unregister(&bcma_bus_type);
 +}
++module_exit(bcma_modexit)
+--- /dev/null
++++ b/drivers/bcma/scan.c
+@@ -0,0 +1,533 @@
++/*
++ * Broadcom specific AMBA
++ * Bus scanning
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
 +
-+extern struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid);
-+extern bool bcma_core_is_enabled(struct bcma_device *core);
-+extern void bcma_core_disable(struct bcma_device *core, u32 flags);
-+extern int bcma_core_enable(struct bcma_device *core, u32 flags);
-+extern void bcma_core_set_clockmode(struct bcma_device *core,
-+				    enum bcma_clkmode clkmode);
-+extern void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status,
-+			      bool on);
-+#define BCMA_DMA_TRANSLATION_MASK	0xC0000000
-+#define  BCMA_DMA_TRANSLATION_NONE	0x00000000
-+#define  BCMA_DMA_TRANSLATION_DMA32_CMT	0x40000000 /* Client Mode Translation for 32-bit DMA */
-+#define  BCMA_DMA_TRANSLATION_DMA64_CMT	0x80000000 /* Client Mode Translation for 64-bit DMA */
-+extern u32 bcma_core_dma_translation(struct bcma_device *core);
++#include "scan.h"
++#include "bcma_private.h"
 +
-+#endif /* LINUX_BCMA_H_ */
---- /dev/null
-+++ b/include/linux/bcma/bcma_driver_chipcommon.h
-@@ -0,0 +1,415 @@
-+#ifndef LINUX_BCMA_DRIVER_CC_H_
-+#define LINUX_BCMA_DRIVER_CC_H_
++#include <linux/bcma/bcma.h>
++#include <linux/bcma/bcma_regs.h>
++#include <linux/pci.h>
++#include <linux/io.h>
++#include <linux/dma-mapping.h>
++#include <linux/slab.h>
 +
-+/** ChipCommon core registers. **/
-+#define BCMA_CC_ID			0x0000
-+#define  BCMA_CC_ID_ID			0x0000FFFF
-+#define  BCMA_CC_ID_ID_SHIFT		0
-+#define  BCMA_CC_ID_REV			0x000F0000
-+#define  BCMA_CC_ID_REV_SHIFT		16
-+#define  BCMA_CC_ID_PKG			0x00F00000
-+#define  BCMA_CC_ID_PKG_SHIFT		20
-+#define  BCMA_CC_ID_NRCORES		0x0F000000
-+#define  BCMA_CC_ID_NRCORES_SHIFT	24
-+#define  BCMA_CC_ID_TYPE		0xF0000000
-+#define  BCMA_CC_ID_TYPE_SHIFT		28
-+#define BCMA_CC_CAP			0x0004		/* Capabilities */
-+#define  BCMA_CC_CAP_NRUART		0x00000003	/* # of UARTs */
-+#define  BCMA_CC_CAP_MIPSEB		0x00000004	/* MIPS in BigEndian Mode */
-+#define  BCMA_CC_CAP_UARTCLK		0x00000018	/* UART clock select */
-+#define   BCMA_CC_CAP_UARTCLK_INT	0x00000008	/* UARTs are driven by internal divided clock */
-+#define  BCMA_CC_CAP_UARTGPIO		0x00000020	/* UARTs on GPIO 15-12 */
-+#define  BCMA_CC_CAP_EXTBUS		0x000000C0	/* External buses present */
-+#define  BCMA_CC_CAP_FLASHT		0x00000700	/* Flash Type */
-+#define   BCMA_CC_FLASHT_NONE		0x00000000	/* No flash */
-+#define   BCMA_CC_FLASHT_STSER		0x00000100	/* ST serial flash */
-+#define   BCMA_CC_FLASHT_ATSER		0x00000200	/* Atmel serial flash */
-+#define   BCMA_CC_FLASHT_NFLASH		0x00000200
-+#define	  BCMA_CC_FLASHT_PARA		0x00000700	/* Parallel flash */
-+#define  BCMA_CC_CAP_PLLT		0x00038000	/* PLL Type */
-+#define   BCMA_PLLTYPE_NONE		0x00000000
-+#define   BCMA_PLLTYPE_1		0x00010000	/* 48Mhz base, 3 dividers */
-+#define   BCMA_PLLTYPE_2		0x00020000	/* 48Mhz, 4 dividers */
-+#define   BCMA_PLLTYPE_3		0x00030000	/* 25Mhz, 2 dividers */
-+#define   BCMA_PLLTYPE_4		0x00008000	/* 48Mhz, 4 dividers */
-+#define   BCMA_PLLTYPE_5		0x00018000	/* 25Mhz, 4 dividers */
-+#define   BCMA_PLLTYPE_6		0x00028000	/* 100/200 or 120/240 only */
-+#define   BCMA_PLLTYPE_7		0x00038000	/* 25Mhz, 4 dividers */
-+#define  BCMA_CC_CAP_PCTL		0x00040000	/* Power Control */
-+#define  BCMA_CC_CAP_OTPS		0x00380000	/* OTP size */
-+#define  BCMA_CC_CAP_OTPS_SHIFT		19
-+#define  BCMA_CC_CAP_OTPS_BASE		5
-+#define  BCMA_CC_CAP_JTAGM		0x00400000	/* JTAG master present */
-+#define  BCMA_CC_CAP_BROM		0x00800000	/* Internal boot ROM active */
-+#define  BCMA_CC_CAP_64BIT		0x08000000	/* 64-bit Backplane */
-+#define  BCMA_CC_CAP_PMU		0x10000000	/* PMU available (rev >= 20) */
-+#define  BCMA_CC_CAP_ECI		0x20000000	/* ECI available (rev >= 20) */
-+#define  BCMA_CC_CAP_SPROM		0x40000000	/* SPROM present */
-+#define BCMA_CC_CORECTL			0x0008
-+#define  BCMA_CC_CORECTL_UARTCLK0	0x00000001	/* Drive UART with internal clock */
-+#define	 BCMA_CC_CORECTL_SE		0x00000002	/* sync clk out enable (corerev >= 3) */
-+#define  BCMA_CC_CORECTL_UARTCLKEN	0x00000008	/* UART clock enable (rev >= 21) */
-+#define BCMA_CC_BIST			0x000C
-+#define BCMA_CC_OTPS			0x0010		/* OTP status */
-+#define	 BCMA_CC_OTPS_PROGFAIL		0x80000000
-+#define	 BCMA_CC_OTPS_PROTECT		0x00000007
-+#define	 BCMA_CC_OTPS_HW_PROTECT	0x00000001
-+#define	 BCMA_CC_OTPS_SW_PROTECT	0x00000002
-+#define	 BCMA_CC_OTPS_CID_PROTECT	0x00000004
-+#define  BCMA_CC_OTPS_GU_PROG_IND	0x00000F00	/* General Use programmed indication */
-+#define  BCMA_CC_OTPS_GU_PROG_IND_SHIFT	8
-+#define  BCMA_CC_OTPS_GU_PROG_HW	0x00000100	/* HW region programmed */
-+#define BCMA_CC_OTPC			0x0014		/* OTP control */
-+#define	 BCMA_CC_OTPC_RECWAIT		0xFF000000
-+#define	 BCMA_CC_OTPC_PROGWAIT		0x00FFFF00
-+#define	 BCMA_CC_OTPC_PRW_SHIFT		8
-+#define	 BCMA_CC_OTPC_MAXFAIL		0x00000038
-+#define	 BCMA_CC_OTPC_VSEL		0x00000006
-+#define	 BCMA_CC_OTPC_SELVL		0x00000001
-+#define BCMA_CC_OTPP			0x0018		/* OTP prog */
-+#define	 BCMA_CC_OTPP_COL		0x000000FF
-+#define	 BCMA_CC_OTPP_ROW		0x0000FF00
-+#define	 BCMA_CC_OTPP_ROW_SHIFT		8
-+#define	 BCMA_CC_OTPP_READERR		0x10000000
-+#define	 BCMA_CC_OTPP_VALUE		0x20000000
-+#define	 BCMA_CC_OTPP_READ		0x40000000
-+#define	 BCMA_CC_OTPP_START		0x80000000
-+#define	 BCMA_CC_OTPP_BUSY		0x80000000
-+#define BCMA_CC_OTPL			0x001C		/* OTP layout */
-+#define  BCMA_CC_OTPL_GURGN_OFFSET	0x00000FFF	/* offset of general use region */
-+#define BCMA_CC_IRQSTAT			0x0020
-+#define BCMA_CC_IRQMASK			0x0024
-+#define	 BCMA_CC_IRQ_GPIO		0x00000001	/* gpio intr */
-+#define	 BCMA_CC_IRQ_EXT		0x00000002	/* ro: ext intr pin (corerev >= 3) */
-+#define	 BCMA_CC_IRQ_WDRESET		0x80000000	/* watchdog reset occurred */
-+#define BCMA_CC_CHIPCTL			0x0028		/* Rev >= 11 only */
-+#define BCMA_CC_CHIPSTAT		0x002C		/* Rev >= 11 only */
-+#define  BCMA_CC_CHIPST_4313_SPROM_PRESENT	1
-+#define  BCMA_CC_CHIPST_4313_OTP_PRESENT	2
-+#define  BCMA_CC_CHIPST_4331_SPROM_PRESENT	2
-+#define  BCMA_CC_CHIPST_4331_OTP_PRESENT	4
-+#define BCMA_CC_JCMD			0x0030		/* Rev >= 10 only */
-+#define  BCMA_CC_JCMD_START		0x80000000
-+#define  BCMA_CC_JCMD_BUSY		0x80000000
-+#define  BCMA_CC_JCMD_PAUSE		0x40000000
-+#define  BCMA_CC_JCMD0_ACC_MASK		0x0000F000
-+#define  BCMA_CC_JCMD0_ACC_IRDR		0x00000000
-+#define  BCMA_CC_JCMD0_ACC_DR		0x00001000
-+#define  BCMA_CC_JCMD0_ACC_IR		0x00002000
-+#define  BCMA_CC_JCMD0_ACC_RESET	0x00003000
-+#define  BCMA_CC_JCMD0_ACC_IRPDR	0x00004000
-+#define  BCMA_CC_JCMD0_ACC_PDR		0x00005000
-+#define  BCMA_CC_JCMD0_IRW_MASK		0x00000F00
-+#define  BCMA_CC_JCMD_ACC_MASK		0x000F0000	/* Changes for corerev 11 */
-+#define  BCMA_CC_JCMD_ACC_IRDR		0x00000000
-+#define  BCMA_CC_JCMD_ACC_DR		0x00010000
-+#define  BCMA_CC_JCMD_ACC_IR		0x00020000
-+#define  BCMA_CC_JCMD_ACC_RESET		0x00030000
-+#define  BCMA_CC_JCMD_ACC_IRPDR		0x00040000
-+#define  BCMA_CC_JCMD_ACC_PDR		0x00050000
-+#define  BCMA_CC_JCMD_IRW_MASK		0x00001F00
-+#define  BCMA_CC_JCMD_IRW_SHIFT		8
-+#define  BCMA_CC_JCMD_DRW_MASK		0x0000003F
-+#define BCMA_CC_JIR			0x0034		/* Rev >= 10 only */
-+#define BCMA_CC_JDR			0x0038		/* Rev >= 10 only */
-+#define BCMA_CC_JCTL			0x003C		/* Rev >= 10 only */
-+#define  BCMA_CC_JCTL_FORCE_CLK		4		/* Force clock */
-+#define  BCMA_CC_JCTL_EXT_EN		2		/* Enable external targets */
-+#define  BCMA_CC_JCTL_EN		1		/* Enable Jtag master */
-+#define BCMA_CC_FLASHCTL		0x0040
-+#define  BCMA_CC_FLASHCTL_START		0x80000000
-+#define  BCMA_CC_FLASHCTL_BUSY		BCMA_CC_FLASHCTL_START
-+#define BCMA_CC_FLASHADDR		0x0044
-+#define BCMA_CC_FLASHDATA		0x0048
-+#define BCMA_CC_BCAST_ADDR		0x0050
-+#define BCMA_CC_BCAST_DATA		0x0054
-+#define BCMA_CC_GPIOPULLUP		0x0058		/* Rev >= 20 only */
-+#define BCMA_CC_GPIOPULLDOWN		0x005C		/* Rev >= 20 only */
-+#define BCMA_CC_GPIOIN			0x0060
-+#define BCMA_CC_GPIOOUT			0x0064
-+#define BCMA_CC_GPIOOUTEN		0x0068
-+#define BCMA_CC_GPIOCTL			0x006C
-+#define BCMA_CC_GPIOPOL			0x0070
-+#define BCMA_CC_GPIOIRQ			0x0074
-+#define BCMA_CC_WATCHDOG		0x0080
-+#define BCMA_CC_GPIOTIMER		0x0088		/* LED powersave (corerev >= 16) */
-+#define  BCMA_CC_GPIOTIMER_OFFTIME	0x0000FFFF
-+#define  BCMA_CC_GPIOTIMER_OFFTIME_SHIFT	0
-+#define  BCMA_CC_GPIOTIMER_ONTIME	0xFFFF0000
-+#define  BCMA_CC_GPIOTIMER_ONTIME_SHIFT	16
-+#define BCMA_CC_GPIOTOUTM		0x008C		/* LED powersave (corerev >= 16) */
-+#define BCMA_CC_CLOCK_N			0x0090
-+#define BCMA_CC_CLOCK_SB		0x0094
-+#define BCMA_CC_CLOCK_PCI		0x0098
-+#define BCMA_CC_CLOCK_M2		0x009C
-+#define BCMA_CC_CLOCK_MIPS		0x00A0
-+#define BCMA_CC_CLKDIV			0x00A4		/* Rev >= 3 only */
-+#define	 BCMA_CC_CLKDIV_SFLASH		0x0F000000
-+#define	 BCMA_CC_CLKDIV_SFLASH_SHIFT	24
-+#define	 BCMA_CC_CLKDIV_OTP		0x000F0000
-+#define	 BCMA_CC_CLKDIV_OTP_SHIFT	16
-+#define	 BCMA_CC_CLKDIV_JTAG		0x00000F00
-+#define	 BCMA_CC_CLKDIV_JTAG_SHIFT	8
-+#define	 BCMA_CC_CLKDIV_UART		0x000000FF
-+#define BCMA_CC_CAP_EXT			0x00AC		/* Capabilities */
-+#define BCMA_CC_PLLONDELAY		0x00B0		/* Rev >= 4 only */
-+#define BCMA_CC_FREFSELDELAY		0x00B4		/* Rev >= 4 only */
-+#define BCMA_CC_SLOWCLKCTL		0x00B8		/* 6 <= Rev <= 9 only */
-+#define  BCMA_CC_SLOWCLKCTL_SRC		0x00000007	/* slow clock source mask */
-+#define	  BCMA_CC_SLOWCLKCTL_SRC_LPO	0x00000000	/* source of slow clock is LPO */
-+#define   BCMA_CC_SLOWCLKCTL_SRC_XTAL	0x00000001	/* source of slow clock is crystal */
-+#define	  BCMA_CC_SLOECLKCTL_SRC_PCI	0x00000002	/* source of slow clock is PCI */
-+#define  BCMA_CC_SLOWCLKCTL_LPOFREQ	0x00000200	/* LPOFreqSel, 1: 160Khz, 0: 32KHz */
-+#define  BCMA_CC_SLOWCLKCTL_LPOPD	0x00000400	/* LPOPowerDown, 1: LPO is disabled, 0: LPO is enabled */
-+#define  BCMA_CC_SLOWCLKCTL_FSLOW	0x00000800	/* ForceSlowClk, 1: sb/cores running on slow clock, 0: power logic control */
-+#define  BCMA_CC_SLOWCLKCTL_IPLL	0x00001000	/* IgnorePllOffReq, 1/0: power logic ignores/honors PLL clock disable requests from core */
-+#define  BCMA_CC_SLOWCLKCTL_ENXTAL	0x00002000	/* XtalControlEn, 1/0: power logic does/doesn't disable crystal when appropriate */
-+#define  BCMA_CC_SLOWCLKCTL_XTALPU	0x00004000	/* XtalPU (RO), 1/0: crystal running/disabled */
-+#define  BCMA_CC_SLOWCLKCTL_CLKDIV	0xFFFF0000	/* ClockDivider (SlowClk = 1/(4+divisor)) */
-+#define  BCMA_CC_SLOWCLKCTL_CLKDIV_SHIFT	16
-+#define BCMA_CC_SYSCLKCTL		0x00C0		/* Rev >= 3 only */
-+#define	 BCMA_CC_SYSCLKCTL_IDLPEN	0x00000001	/* ILPen: Enable Idle Low Power */
-+#define	 BCMA_CC_SYSCLKCTL_ALPEN	0x00000002	/* ALPen: Enable Active Low Power */
-+#define	 BCMA_CC_SYSCLKCTL_PLLEN	0x00000004	/* ForcePLLOn */
-+#define	 BCMA_CC_SYSCLKCTL_FORCEALP	0x00000008	/* Force ALP (or HT if ALPen is not set */
-+#define	 BCMA_CC_SYSCLKCTL_FORCEHT	0x00000010	/* Force HT */
-+#define  BCMA_CC_SYSCLKCTL_CLKDIV	0xFFFF0000	/* ClkDiv  (ILP = 1/(4+divisor)) */
-+#define  BCMA_CC_SYSCLKCTL_CLKDIV_SHIFT	16
-+#define BCMA_CC_CLKSTSTR		0x00C4		/* Rev >= 3 only */
-+#define BCMA_CC_EROM			0x00FC
-+#define BCMA_CC_PCMCIA_CFG		0x0100
-+#define BCMA_CC_PCMCIA_MEMWAIT		0x0104
-+#define BCMA_CC_PCMCIA_ATTRWAIT		0x0108
-+#define BCMA_CC_PCMCIA_IOWAIT		0x010C
-+#define BCMA_CC_IDE_CFG			0x0110
-+#define BCMA_CC_IDE_MEMWAIT		0x0114
-+#define BCMA_CC_IDE_ATTRWAIT		0x0118
-+#define BCMA_CC_IDE_IOWAIT		0x011C
-+#define BCMA_CC_PROG_CFG		0x0120
-+#define BCMA_CC_PROG_WAITCNT		0x0124
-+#define BCMA_CC_FLASH_CFG		0x0128
-+#define  BCMA_CC_FLASH_CFG_DS		0x0010	/* Data size, 0=8bit, 1=16bit */
-+#define BCMA_CC_FLASH_WAITCNT		0x012C
-+#define BCMA_CC_SROM_CONTROL		0x0190
-+#define  BCMA_CC_SROM_CONTROL_START	0x80000000
-+#define  BCMA_CC_SROM_CONTROL_BUSY	0x80000000
-+#define  BCMA_CC_SROM_CONTROL_OPCODE	0x60000000
-+#define  BCMA_CC_SROM_CONTROL_OP_READ	0x00000000
-+#define  BCMA_CC_SROM_CONTROL_OP_WRITE	0x20000000
-+#define  BCMA_CC_SROM_CONTROL_OP_WRDIS	0x40000000
-+#define  BCMA_CC_SROM_CONTROL_OP_WREN	0x60000000
-+#define  BCMA_CC_SROM_CONTROL_OTPSEL	0x00000010
-+#define  BCMA_CC_SROM_CONTROL_LOCK	0x00000008
-+#define  BCMA_CC_SROM_CONTROL_SIZE_MASK	0x00000006
-+#define  BCMA_CC_SROM_CONTROL_SIZE_1K	0x00000000
-+#define  BCMA_CC_SROM_CONTROL_SIZE_4K	0x00000002
-+#define  BCMA_CC_SROM_CONTROL_SIZE_16K	0x00000004
-+#define  BCMA_CC_SROM_CONTROL_SIZE_SHIFT	1
-+#define  BCMA_CC_SROM_CONTROL_PRESENT	0x00000001
-+/* 0x1E0 is defined as shared BCMA_CLKCTLST */
-+#define BCMA_CC_HW_WORKAROUND		0x01E4 /* Hardware workaround (rev >= 20) */
-+#define BCMA_CC_UART0_DATA		0x0300
-+#define BCMA_CC_UART0_IMR		0x0304
-+#define BCMA_CC_UART0_FCR		0x0308
-+#define BCMA_CC_UART0_LCR		0x030C
-+#define BCMA_CC_UART0_MCR		0x0310
-+#define BCMA_CC_UART0_LSR		0x0314
-+#define BCMA_CC_UART0_MSR		0x0318
-+#define BCMA_CC_UART0_SCRATCH		0x031C
-+#define BCMA_CC_UART1_DATA		0x0400
-+#define BCMA_CC_UART1_IMR		0x0404
-+#define BCMA_CC_UART1_FCR		0x0408
-+#define BCMA_CC_UART1_LCR		0x040C
-+#define BCMA_CC_UART1_MCR		0x0410
-+#define BCMA_CC_UART1_LSR		0x0414
-+#define BCMA_CC_UART1_MSR		0x0418
-+#define BCMA_CC_UART1_SCRATCH		0x041C
-+/* PMU registers (rev >= 20) */
-+#define BCMA_CC_PMU_CTL			0x0600 /* PMU control */
-+#define  BCMA_CC_PMU_CTL_ILP_DIV	0xFFFF0000 /* ILP div mask */
-+#define  BCMA_CC_PMU_CTL_ILP_DIV_SHIFT	16
-+#define  BCMA_CC_PMU_CTL_PLL_UPD	0x00000400
-+#define  BCMA_CC_PMU_CTL_NOILPONW	0x00000200 /* No ILP on wait */
-+#define  BCMA_CC_PMU_CTL_HTREQEN	0x00000100 /* HT req enable */
-+#define  BCMA_CC_PMU_CTL_ALPREQEN	0x00000080 /* ALP req enable */
-+#define  BCMA_CC_PMU_CTL_XTALFREQ	0x0000007C /* Crystal freq */
-+#define  BCMA_CC_PMU_CTL_XTALFREQ_SHIFT	2
-+#define  BCMA_CC_PMU_CTL_ILPDIVEN	0x00000002 /* ILP div enable */
-+#define  BCMA_CC_PMU_CTL_LPOSEL		0x00000001 /* LPO sel */
-+#define BCMA_CC_PMU_CAP			0x0604 /* PMU capabilities */
-+#define  BCMA_CC_PMU_CAP_REVISION	0x000000FF /* Revision mask */
-+#define BCMA_CC_PMU_STAT		0x0608 /* PMU status */
-+#define  BCMA_CC_PMU_STAT_INTPEND	0x00000040 /* Interrupt pending */
-+#define  BCMA_CC_PMU_STAT_SBCLKST	0x00000030 /* Backplane clock status? */
-+#define  BCMA_CC_PMU_STAT_HAVEALP	0x00000008 /* ALP available */
-+#define  BCMA_CC_PMU_STAT_HAVEHT	0x00000004 /* HT available */
-+#define  BCMA_CC_PMU_STAT_RESINIT	0x00000003 /* Res init */
-+#define BCMA_CC_PMU_RES_STAT		0x060C /* PMU res status */
-+#define BCMA_CC_PMU_RES_PEND		0x0610 /* PMU res pending */
-+#define BCMA_CC_PMU_TIMER		0x0614 /* PMU timer */
-+#define BCMA_CC_PMU_MINRES_MSK		0x0618 /* PMU min res mask */
-+#define BCMA_CC_PMU_MAXRES_MSK		0x061C /* PMU max res mask */
-+#define BCMA_CC_PMU_RES_TABSEL		0x0620 /* PMU res table sel */
-+#define BCMA_CC_PMU_RES_DEPMSK		0x0624 /* PMU res dep mask */
-+#define BCMA_CC_PMU_RES_UPDNTM		0x0628 /* PMU res updown timer */
-+#define BCMA_CC_PMU_RES_TIMER		0x062C /* PMU res timer */
-+#define BCMA_CC_PMU_CLKSTRETCH		0x0630 /* PMU clockstretch */
-+#define BCMA_CC_PMU_WATCHDOG		0x0634 /* PMU watchdog */
-+#define BCMA_CC_PMU_RES_REQTS		0x0640 /* PMU res req timer sel */
-+#define BCMA_CC_PMU_RES_REQT		0x0644 /* PMU res req timer */
-+#define BCMA_CC_PMU_RES_REQM		0x0648 /* PMU res req mask */
-+#define BCMA_CC_CHIPCTL_ADDR		0x0650
-+#define BCMA_CC_CHIPCTL_DATA		0x0654
-+#define BCMA_CC_REGCTL_ADDR		0x0658
-+#define BCMA_CC_REGCTL_DATA		0x065C
-+#define BCMA_CC_PLLCTL_ADDR		0x0660
-+#define BCMA_CC_PLLCTL_DATA		0x0664
-+#define BCMA_CC_SPROM			0x0800 /* SPROM beginning */
++struct bcma_device_id_name {
++	u16 id;
++	const char *name;
++};
 +
-+/* Divider allocation in 4716/47162/5356 */
-+#define BCMA_CC_PMU5_MAINPLL_CPU	1
-+#define BCMA_CC_PMU5_MAINPLL_MEM	2
-+#define BCMA_CC_PMU5_MAINPLL_SSB	3
++static const struct bcma_device_id_name bcma_arm_device_names[] = {
++	{ BCMA_CORE_ARM_1176, "ARM 1176" },
++	{ BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },
++	{ BCMA_CORE_ARM_CM3, "ARM CM3" },
++};
 +
-+/* PLL usage in 4716/47162 */
-+#define BCMA_CC_PMU4716_MAINPLL_PLL0	12
++static const struct bcma_device_id_name bcma_bcm_device_names[] = {
++	{ BCMA_CORE_OOB_ROUTER, "OOB Router" },
++	{ BCMA_CORE_INVALID, "Invalid" },
++	{ BCMA_CORE_CHIPCOMMON, "ChipCommon" },
++	{ BCMA_CORE_ILINE20, "ILine 20" },
++	{ BCMA_CORE_SRAM, "SRAM" },
++	{ BCMA_CORE_SDRAM, "SDRAM" },
++	{ BCMA_CORE_PCI, "PCI" },
++	{ BCMA_CORE_ETHERNET, "Fast Ethernet" },
++	{ BCMA_CORE_V90, "V90" },
++	{ BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" },
++	{ BCMA_CORE_ADSL, "ADSL" },
++	{ BCMA_CORE_ILINE100, "ILine 100" },
++	{ BCMA_CORE_IPSEC, "IPSEC" },
++	{ BCMA_CORE_UTOPIA, "UTOPIA" },
++	{ BCMA_CORE_PCMCIA, "PCMCIA" },
++	{ BCMA_CORE_INTERNAL_MEM, "Internal Memory" },
++	{ BCMA_CORE_MEMC_SDRAM, "MEMC SDRAM" },
++	{ BCMA_CORE_OFDM, "OFDM" },
++	{ BCMA_CORE_EXTIF, "EXTIF" },
++	{ BCMA_CORE_80211, "IEEE 802.11" },
++	{ BCMA_CORE_PHY_A, "PHY A" },
++	{ BCMA_CORE_PHY_B, "PHY B" },
++	{ BCMA_CORE_PHY_G, "PHY G" },
++	{ BCMA_CORE_USB11_HOST, "USB 1.1 Host" },
++	{ BCMA_CORE_USB11_DEV, "USB 1.1 Device" },
++	{ BCMA_CORE_USB20_HOST, "USB 2.0 Host" },
++	{ BCMA_CORE_USB20_DEV, "USB 2.0 Device" },
++	{ BCMA_CORE_SDIO_HOST, "SDIO Host" },
++	{ BCMA_CORE_ROBOSWITCH, "Roboswitch" },
++	{ BCMA_CORE_PARA_ATA, "PATA" },
++	{ BCMA_CORE_SATA_XORDMA, "SATA XOR-DMA" },
++	{ BCMA_CORE_ETHERNET_GBIT, "GBit Ethernet" },
++	{ BCMA_CORE_PCIE, "PCIe" },
++	{ BCMA_CORE_PHY_N, "PHY N" },
++	{ BCMA_CORE_SRAM_CTL, "SRAM Controller" },
++	{ BCMA_CORE_MINI_MACPHY, "Mini MACPHY" },
++	{ BCMA_CORE_PHY_LP, "PHY LP" },
++	{ BCMA_CORE_PMU, "PMU" },
++	{ BCMA_CORE_PHY_SSN, "PHY SSN" },
++	{ BCMA_CORE_SDIO_DEV, "SDIO Device" },
++	{ BCMA_CORE_PHY_HT, "PHY HT" },
++	{ BCMA_CORE_MAC_GBIT, "GBit MAC" },
++	{ BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" },
++	{ BCMA_CORE_PCIE_RC, "PCIe Root Complex" },
++	{ BCMA_CORE_OCP_OCP_BRIDGE, "OCP to OCP Bridge" },
++	{ BCMA_CORE_SHARED_COMMON, "Common Shared" },
++	{ BCMA_CORE_OCP_AHB_BRIDGE, "OCP to AHB Bridge" },
++	{ BCMA_CORE_SPI_HOST, "SPI Host" },
++	{ BCMA_CORE_I2S, "I2S" },
++	{ BCMA_CORE_SDR_DDR1_MEM_CTL, "SDR/DDR1 Memory Controller" },
++	{ BCMA_CORE_SHIM, "SHIM" },
++	{ BCMA_CORE_DEFAULT, "Default" },
++};
 +
-+/* PLL usage in 5356/5357 */
-+#define BCMA_CC_PMU5356_MAINPLL_PLL0	0
-+#define BCMA_CC_PMU5357_MAINPLL_PLL0	0
++static const struct bcma_device_id_name bcma_mips_device_names[] = {
++	{ BCMA_CORE_MIPS, "MIPS" },
++	{ BCMA_CORE_MIPS_3302, "MIPS 3302" },
++	{ BCMA_CORE_MIPS_74K, "MIPS 74K" },
++};
 +
-+/* 4706 PMU */
-+#define BCMA_CC_PMU4706_MAINPLL_PLL0	0
++static const char *bcma_device_name(const struct bcma_device_id *id)
++{
++	const struct bcma_device_id_name *names;
++	int size, i;
 +
-+/* ALP clock on pre-PMU chips */
-+#define BCMA_CC_PMU_ALP_CLOCK		20000000
-+/* HT clock for systems with PMU-enabled chipcommon */
-+#define BCMA_CC_PMU_HT_CLOCK		80000000
++	/* search manufacturer specific names */
++	switch (id->manuf) {
++	case BCMA_MANUF_ARM:
++		names = bcma_arm_device_names;
++		size = ARRAY_SIZE(bcma_arm_device_names);
++		break;
++	case BCMA_MANUF_BCM:
++		names = bcma_bcm_device_names;
++		size = ARRAY_SIZE(bcma_bcm_device_names);
++		break;
++	case BCMA_MANUF_MIPS:
++		names = bcma_mips_device_names;
++		size = ARRAY_SIZE(bcma_mips_device_names);
++		break;
++	default:
++		return "UNKNOWN";
++	}
++
++	for (i = 0; i < size; i++) {
++		if (names[i].id == id->id)
++			return names[i].name;
++	}
++
++	return "UNKNOWN";
++}
++
++static u32 bcma_scan_read32(struct bcma_bus *bus, u8 current_coreidx,
++		       u16 offset)
++{
++	return readl(bus->mmio + offset);
++}
++
++static void bcma_scan_switch_core(struct bcma_bus *bus, u32 addr)
++{
++	if (bus->hosttype == BCMA_HOSTTYPE_PCI)
++		pci_write_config_dword(bus->host_pci, BCMA_PCI_BAR0_WIN,
++				       addr);
++}
++
++static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 **eromptr)
++{
++	u32 ent = readl(*eromptr);
++	(*eromptr)++;
++	return ent;
++}
++
++static void bcma_erom_push_ent(u32 **eromptr)
++{
++	(*eromptr)--;
++}
++
++static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr)
++{
++	u32 ent = bcma_erom_get_ent(bus, eromptr);
++	if (!(ent & SCAN_ER_VALID))
++		return -ENOENT;
++	if ((ent & SCAN_ER_TAG) != SCAN_ER_TAG_CI)
++		return -ENOENT;
++	return ent;
++}
++
++static bool bcma_erom_is_end(struct bcma_bus *bus, u32 **eromptr)
++{
++	u32 ent = bcma_erom_get_ent(bus, eromptr);
++	bcma_erom_push_ent(eromptr);
++	return (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID));
++}
++
++static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 **eromptr)
++{
++	u32 ent = bcma_erom_get_ent(bus, eromptr);
++	bcma_erom_push_ent(eromptr);
++	return (((ent & SCAN_ER_VALID)) &&
++		((ent & SCAN_ER_TAGX) == SCAN_ER_TAG_ADDR) &&
++		((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE));
++}
++
++static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr)
++{
++	u32 ent;
++	while (1) {
++		ent = bcma_erom_get_ent(bus, eromptr);
++		if ((ent & SCAN_ER_VALID) &&
++		    ((ent & SCAN_ER_TAG) == SCAN_ER_TAG_CI))
++			break;
++		if (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID))
++			break;
++	}
++	bcma_erom_push_ent(eromptr);
++}
++
++static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr)
++{
++	u32 ent = bcma_erom_get_ent(bus, eromptr);
++	if (!(ent & SCAN_ER_VALID))
++		return -ENOENT;
++	if ((ent & SCAN_ER_TAG) != SCAN_ER_TAG_MP)
++		return -ENOENT;
++	return ent;
++}
++
++static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr,
++				  u32 type, u8 port)
++{
++	u32 addrl, addrh, sizel, sizeh = 0;
++	u32 size;
++
++	u32 ent = bcma_erom_get_ent(bus, eromptr);
++	if ((!(ent & SCAN_ER_VALID)) ||
++	    ((ent & SCAN_ER_TAGX) != SCAN_ER_TAG_ADDR) ||
++	    ((ent & SCAN_ADDR_TYPE) != type) ||
++	    (((ent & SCAN_ADDR_PORT) >> SCAN_ADDR_PORT_SHIFT) != port)) {
++		bcma_erom_push_ent(eromptr);
++		return -EINVAL;
++	}
 +
-+/* PMU rev 5 (& 6) */
-+#define BCMA_CC_PPL_P1P2_OFF		0
-+#define BCMA_CC_PPL_P1_MASK		0x0f000000
-+#define BCMA_CC_PPL_P1_SHIFT		24
-+#define BCMA_CC_PPL_P2_MASK		0x00f00000
-+#define BCMA_CC_PPL_P2_SHIFT		20
-+#define BCMA_CC_PPL_M14_OFF		1
-+#define BCMA_CC_PPL_MDIV_MASK		0x000000ff
-+#define BCMA_CC_PPL_MDIV_WIDTH		8
-+#define BCMA_CC_PPL_NM5_OFF		2
-+#define BCMA_CC_PPL_NDIV_MASK		0xfff00000
-+#define BCMA_CC_PPL_NDIV_SHIFT		20
-+#define BCMA_CC_PPL_FMAB_OFF		3
-+#define BCMA_CC_PPL_MRAT_MASK		0xf0000000
-+#define BCMA_CC_PPL_MRAT_SHIFT		28
-+#define BCMA_CC_PPL_ABRAT_MASK		0x08000000
-+#define BCMA_CC_PPL_ABRAT_SHIFT		27
-+#define BCMA_CC_PPL_FDIV_MASK		0x07ffffff
-+#define BCMA_CC_PPL_PLLCTL_OFF		4
-+#define BCMA_CC_PPL_PCHI_OFF		5
-+#define BCMA_CC_PPL_PCHI_MASK		0x0000003f
++	addrl = ent & SCAN_ADDR_ADDR;
++	if (ent & SCAN_ADDR_AG32)
++		addrh = bcma_erom_get_ent(bus, eromptr);
++	else
++		addrh = 0;
 +
-+/* BCM4331 ChipControl numbers. */
-+#define BCMA_CHIPCTL_4331_BT_COEXIST		BIT(0)	/* 0 disable */
-+#define BCMA_CHIPCTL_4331_SECI			BIT(1)	/* 0 SECI is disabled (JATG functional) */
-+#define BCMA_CHIPCTL_4331_EXT_LNA		BIT(2)	/* 0 disable */
-+#define BCMA_CHIPCTL_4331_SPROM_GPIO13_15	BIT(3)	/* sprom/gpio13-15 mux */
-+#define BCMA_CHIPCTL_4331_EXTPA_EN		BIT(4)	/* 0 ext pa disable, 1 ext pa enabled */
-+#define BCMA_CHIPCTL_4331_GPIOCLK_ON_SPROMCS	BIT(5)	/* set drive out GPIO_CLK on sprom_cs pin */
-+#define BCMA_CHIPCTL_4331_PCIE_MDIO_ON_SPROMCS	BIT(6)	/* use sprom_cs pin as PCIE mdio interface */
-+#define BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5	BIT(7)	/* aband extpa will be at gpio2/5 and sprom_dout */
-+#define BCMA_CHIPCTL_4331_OVR_PIPEAUXCLKEN	BIT(8)	/* override core control on pipe_AuxClkEnable */
-+#define BCMA_CHIPCTL_4331_OVR_PIPEAUXPWRDOWN	BIT(9)	/* override core control on pipe_AuxPowerDown */
-+#define BCMA_CHIPCTL_4331_PCIE_AUXCLKEN		BIT(10)	/* pcie_auxclkenable */
-+#define BCMA_CHIPCTL_4331_PCIE_PIPE_PLLDOWN	BIT(11)	/* pcie_pipe_pllpowerdown */
-+#define BCMA_CHIPCTL_4331_BT_SHD0_ON_GPIO4	BIT(16)	/* enable bt_shd0 at gpio4 */
-+#define BCMA_CHIPCTL_4331_BT_SHD1_ON_GPIO5	BIT(17)	/* enable bt_shd1 at gpio5 */
++	if ((ent & SCAN_ADDR_SZ) == SCAN_ADDR_SZ_SZD) {
++		size = bcma_erom_get_ent(bus, eromptr);
++		sizel = size & SCAN_SIZE_SZ;
++		if (size & SCAN_SIZE_SG32)
++			sizeh = bcma_erom_get_ent(bus, eromptr);
++	} else
++		sizel = SCAN_ADDR_SZ_BASE <<
++				((ent & SCAN_ADDR_SZ) >> SCAN_ADDR_SZ_SHIFT);
 +
-+/* Data for the PMU, if available.
-+ * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
-+ */
-+struct bcma_chipcommon_pmu {
-+	u8 rev;			/* PMU revision */
-+	u32 crystalfreq;	/* The active crystal frequency (in kHz) */
-+};
++	return addrl;
++}
 +
-+#ifdef CONFIG_BCMA_DRIVER_MIPS
-+struct bcma_pflash {
-+	u8 buswidth;
-+	u32 window;
-+	u32 window_size;
-+};
++static struct bcma_device *bcma_find_core_by_index(struct bcma_bus *bus,
++						   u16 index)
++{
++	struct bcma_device *core;
 +
-+struct bcma_serial_port {
-+	void *regs;
-+	unsigned long clockspeed;
-+	unsigned int irq;
-+	unsigned int baud_base;
-+	unsigned int reg_shift;
-+};
-+#endif /* CONFIG_BCMA_DRIVER_MIPS */
++	list_for_each_entry(core, &bus->cores, list) {
++		if (core->core_index == index)
++			return core;
++	}
++	return NULL;
++}
 +
-+struct bcma_drv_cc {
++static struct bcma_device *bcma_find_core_reverse(struct bcma_bus *bus, u16 coreid)
++{
 +	struct bcma_device *core;
-+	u32 status;
-+	u32 capabilities;
-+	u32 capabilities_ext;
-+	u8 setup_done:1;
-+	/* Fast Powerup Delay constant */
-+	u16 fast_pwrup_delay;
-+	struct bcma_chipcommon_pmu pmu;
-+#ifdef CONFIG_BCMA_DRIVER_MIPS
-+	struct bcma_pflash pflash;
 +
-+	int nr_serial_ports;
-+	struct bcma_serial_port serial_ports[4];
-+#endif /* CONFIG_BCMA_DRIVER_MIPS */
-+};
++	list_for_each_entry_reverse(core, &bus->cores, list) {
++		if (core->id.id == coreid)
++			return core;
++	}
++	return NULL;
++}
 +
-+/* Register access */
-+#define bcma_cc_read32(cc, offset) \
-+	bcma_read32((cc)->core, offset)
-+#define bcma_cc_write32(cc, offset, val) \
-+	bcma_write32((cc)->core, offset, val)
++static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
++			      struct bcma_device_id *match, int core_num,
++			      struct bcma_device *core)
++{
++	s32 tmp;
++	u8 i, j;
++	s32 cia, cib;
++	u8 ports[2], wrappers[2];
 +
-+#define bcma_cc_mask32(cc, offset, mask) \
-+	bcma_cc_write32(cc, offset, bcma_cc_read32(cc, offset) & (mask))
-+#define bcma_cc_set32(cc, offset, set) \
-+	bcma_cc_write32(cc, offset, bcma_cc_read32(cc, offset) | (set))
-+#define bcma_cc_maskset32(cc, offset, mask, set) \
-+	bcma_cc_write32(cc, offset, (bcma_cc_read32(cc, offset) & (mask)) | (set))
++	/* get CIs */
++	cia = bcma_erom_get_ci(bus, eromptr);
++	if (cia < 0) {
++		bcma_erom_push_ent(eromptr);
++		if (bcma_erom_is_end(bus, eromptr))
++			return -ESPIPE;
++		return -EILSEQ;
++	}
++	cib = bcma_erom_get_ci(bus, eromptr);
++	if (cib < 0)
++		return -EILSEQ;
 +
-+extern void bcma_core_chipcommon_init(struct bcma_drv_cc *cc);
++	/* parse CIs */
++	core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
++	core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
++	core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT;
++	ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT;
++	ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT;
++	wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT;
++	wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT;
++	core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;
 +
-+extern void bcma_chipco_suspend(struct bcma_drv_cc *cc);
-+extern void bcma_chipco_resume(struct bcma_drv_cc *cc);
++	if (((core->id.manuf == BCMA_MANUF_ARM) &&
++	     (core->id.id == 0xFFF)) ||
++	    (ports[1] == 0)) {
++		bcma_erom_skip_component(bus, eromptr);
++		return -ENXIO;
++	}
 +
-+void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable);
++	/* check if component is a core at all */
++	if (wrappers[0] + wrappers[1] == 0) {
++		/* we could save addrl of the router
++		if (cid == BCMA_CORE_OOB_ROUTER)
++		 */
++		bcma_erom_skip_component(bus, eromptr);
++		return -ENXIO;
++	}
 +
-+extern void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc,
-+					  u32 ticks);
++	if (bcma_erom_is_bridge(bus, eromptr)) {
++		bcma_erom_skip_component(bus, eromptr);
++		return -ENXIO;
++	}
 +
-+void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value);
++	if (bcma_find_core_by_index(bus, core_num)) {
++		bcma_erom_skip_component(bus, eromptr);
++		return -ENODEV;
++	}
 +
-+u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask);
++	if (match && ((match->manuf != BCMA_ANY_MANUF &&
++	      match->manuf != core->id.manuf) ||
++	     (match->id != BCMA_ANY_ID && match->id != core->id.id) ||
++	     (match->rev != BCMA_ANY_REV && match->rev != core->id.rev) ||
++	     (match->class != BCMA_ANY_CLASS && match->class != core->id.class)
++	    )) {
++		bcma_erom_skip_component(bus, eromptr);
++		return -ENODEV;
++	}
 +
-+/* Chipcommon GPIO pin access. */
-+u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask);
-+u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value);
-+u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value);
-+u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value);
-+u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value);
-+u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value);
++	/* get & parse master ports */
++	for (i = 0; i < ports[0]; i++) {
++		s32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr);
++		if (mst_port_d < 0)
++			return -EILSEQ;
++	}
 +
-+/* PMU support */
-+extern void bcma_pmu_init(struct bcma_drv_cc *cc);
++	/* get & parse slave ports */
++	for (i = 0; i < ports[1]; i++) {
++		for (j = 0; ; j++) {
++			tmp = bcma_erom_get_addr_desc(bus, eromptr,
++				SCAN_ADDR_TYPE_SLAVE, i);
++			if (tmp < 0) {
++				/* no more entries for port _i_ */
++				/* pr_debug("erom: slave port %d "
++				 * "has %d descriptors\n", i, j); */
++				break;
++			} else {
++				if (i == 0 && j == 0)
++					core->addr = tmp;
++			}
++		}
++	}
 +
-+extern void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset,
-+				  u32 value);
-+extern void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset,
-+				    u32 mask, u32 set);
-+extern void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
-+					u32 offset, u32 mask, u32 set);
-+extern void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc,
-+				       u32 offset, u32 mask, u32 set);
++	/* get & parse master wrappers */
++	for (i = 0; i < wrappers[0]; i++) {
++		for (j = 0; ; j++) {
++			tmp = bcma_erom_get_addr_desc(bus, eromptr,
++				SCAN_ADDR_TYPE_MWRAP, i);
++			if (tmp < 0) {
++				/* no more entries for port _i_ */
++				/* pr_debug("erom: master wrapper %d "
++				 * "has %d descriptors\n", i, j); */
++				break;
++			} else {
++				if (i == 0 && j == 0)
++					core->wrap = tmp;
++			}
++		}
++	}
++
++	/* get & parse slave wrappers */
++	for (i = 0; i < wrappers[1]; i++) {
++		u8 hack = (ports[1] == 1) ? 0 : 1;
++		for (j = 0; ; j++) {
++			tmp = bcma_erom_get_addr_desc(bus, eromptr,
++				SCAN_ADDR_TYPE_SWRAP, i + hack);
++			if (tmp < 0) {
++				/* no more entries for port _i_ */
++				/* pr_debug("erom: master wrapper %d "
++				 * has %d descriptors\n", i, j); */
++				break;
++			} else {
++				if (wrappers[0] == 0 && !i && !j)
++					core->wrap = tmp;
++			}
++		}
++	}
++	if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
++		core->io_addr = ioremap_nocache(core->addr, BCMA_CORE_SIZE);
++		if (!core->io_addr)
++			return -ENOMEM;
++		core->io_wrap = ioremap_nocache(core->wrap, BCMA_CORE_SIZE);
++		if (!core->io_wrap) {
++			iounmap(core->io_addr);
++			return -ENOMEM;
++		}
++	}
++	return 0;
++}
 +
-+#endif /* LINUX_BCMA_DRIVER_CC_H_ */
---- /dev/null
-+++ b/include/linux/bcma/bcma_driver_pci.h
-@@ -0,0 +1,214 @@
-+#ifndef LINUX_BCMA_DRIVER_PCI_H_
-+#define LINUX_BCMA_DRIVER_PCI_H_
++void bcma_init_bus(struct bcma_bus *bus)
++{
++	s32 tmp;
++	struct bcma_chipinfo *chipinfo = &(bus->chipinfo);
 +
-+#include <linux/types.h>
++	if (bus->init_done)
++		return;
 +
-+struct pci_dev;
++	INIT_LIST_HEAD(&bus->cores);
++	bus->nr_cores = 0;
 +
-+/** PCI core registers. **/
-+#define BCMA_CORE_PCI_CTL			0x0000	/* PCI Control */
-+#define  BCMA_CORE_PCI_CTL_RST_OE		0x00000001 /* PCI_RESET Output Enable */
-+#define  BCMA_CORE_PCI_CTL_RST			0x00000002 /* PCI_RESET driven out to pin */
-+#define  BCMA_CORE_PCI_CTL_CLK_OE		0x00000004 /* Clock gate Output Enable */
-+#define  BCMA_CORE_PCI_CTL_CLK			0x00000008 /* Gate for clock driven out to pin */
-+#define BCMA_CORE_PCI_ARBCTL			0x0010	/* PCI Arbiter Control */
-+#define  BCMA_CORE_PCI_ARBCTL_INTERN		0x00000001 /* Use internal arbiter */
-+#define  BCMA_CORE_PCI_ARBCTL_EXTERN		0x00000002 /* Use external arbiter */
-+#define  BCMA_CORE_PCI_ARBCTL_PARKID		0x00000006 /* Mask, selects which agent is parked on an idle bus */
-+#define   BCMA_CORE_PCI_ARBCTL_PARKID_LAST	0x00000000 /* Last requestor */
-+#define   BCMA_CORE_PCI_ARBCTL_PARKID_4710	0x00000002 /* 4710 */
-+#define   BCMA_CORE_PCI_ARBCTL_PARKID_EXT0	0x00000004 /* External requestor 0 */
-+#define   BCMA_CORE_PCI_ARBCTL_PARKID_EXT1	0x00000006 /* External requestor 1 */
-+#define BCMA_CORE_PCI_ISTAT			0x0020	/* Interrupt status */
-+#define  BCMA_CORE_PCI_ISTAT_INTA		0x00000001 /* PCI INTA# */
-+#define  BCMA_CORE_PCI_ISTAT_INTB		0x00000002 /* PCI INTB# */
-+#define  BCMA_CORE_PCI_ISTAT_SERR		0x00000004 /* PCI SERR# (write to clear) */
-+#define  BCMA_CORE_PCI_ISTAT_PERR		0x00000008 /* PCI PERR# (write to clear) */
-+#define  BCMA_CORE_PCI_ISTAT_PME		0x00000010 /* PCI PME# */
-+#define BCMA_CORE_PCI_IMASK			0x0024	/* Interrupt mask */
-+#define  BCMA_CORE_PCI_IMASK_INTA		0x00000001 /* PCI INTA# */
-+#define  BCMA_CORE_PCI_IMASK_INTB		0x00000002 /* PCI INTB# */
-+#define  BCMA_CORE_PCI_IMASK_SERR		0x00000004 /* PCI SERR# */
-+#define  BCMA_CORE_PCI_IMASK_PERR		0x00000008 /* PCI PERR# */
-+#define  BCMA_CORE_PCI_IMASK_PME		0x00000010 /* PCI PME# */
-+#define BCMA_CORE_PCI_MBOX			0x0028	/* Backplane to PCI Mailbox */
-+#define  BCMA_CORE_PCI_MBOX_F0_0		0x00000100 /* PCI function 0, INT 0 */
-+#define  BCMA_CORE_PCI_MBOX_F0_1		0x00000200 /* PCI function 0, INT 1 */
-+#define  BCMA_CORE_PCI_MBOX_F1_0		0x00000400 /* PCI function 1, INT 0 */
-+#define  BCMA_CORE_PCI_MBOX_F1_1		0x00000800 /* PCI function 1, INT 1 */
-+#define  BCMA_CORE_PCI_MBOX_F2_0		0x00001000 /* PCI function 2, INT 0 */
-+#define  BCMA_CORE_PCI_MBOX_F2_1		0x00002000 /* PCI function 2, INT 1 */
-+#define  BCMA_CORE_PCI_MBOX_F3_0		0x00004000 /* PCI function 3, INT 0 */
-+#define  BCMA_CORE_PCI_MBOX_F3_1		0x00008000 /* PCI function 3, INT 1 */
-+#define BCMA_CORE_PCI_BCAST_ADDR		0x0050	/* Backplane Broadcast Address */
-+#define  BCMA_CORE_PCI_BCAST_ADDR_MASK		0x000000FF
-+#define BCMA_CORE_PCI_BCAST_DATA		0x0054	/* Backplane Broadcast Data */
-+#define BCMA_CORE_PCI_GPIO_IN			0x0060	/* rev >= 2 only */
-+#define BCMA_CORE_PCI_GPIO_OUT			0x0064	/* rev >= 2 only */
-+#define BCMA_CORE_PCI_GPIO_ENABLE		0x0068	/* rev >= 2 only */
-+#define BCMA_CORE_PCI_GPIO_CTL			0x006C	/* rev >= 2 only */
-+#define BCMA_CORE_PCI_SBTOPCI0			0x0100	/* Backplane to PCI translation 0 (sbtopci0) */
-+#define  BCMA_CORE_PCI_SBTOPCI0_MASK		0xFC000000
-+#define BCMA_CORE_PCI_SBTOPCI1			0x0104	/* Backplane to PCI translation 1 (sbtopci1) */
-+#define  BCMA_CORE_PCI_SBTOPCI1_MASK		0xFC000000
-+#define BCMA_CORE_PCI_SBTOPCI2			0x0108	/* Backplane to PCI translation 2 (sbtopci2) */
-+#define  BCMA_CORE_PCI_SBTOPCI2_MASK		0xC0000000
-+#define BCMA_CORE_PCI_CONFIG_ADDR		0x0120	/* pcie config space access */
-+#define BCMA_CORE_PCI_CONFIG_DATA		0x0124	/* pcie config space access */
-+#define BCMA_CORE_PCI_MDIO_CONTROL		0x0128	/* controls the mdio access */
-+#define  BCMA_CORE_PCI_MDIOCTL_DIVISOR_MASK	0x7f	/* clock to be used on MDIO */
-+#define  BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL	0x2
-+#define  BCMA_CORE_PCI_MDIOCTL_PREAM_EN		0x80	/* Enable preamble sequnce */
-+#define  BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE	0x100	/* Tranaction complete */
-+#define BCMA_CORE_PCI_MDIO_DATA			0x012c	/* Data to the mdio access */
-+#define  BCMA_CORE_PCI_MDIODATA_MASK		0x0000ffff /* data 2 bytes */
-+#define  BCMA_CORE_PCI_MDIODATA_TA		0x00020000 /* Turnaround */
-+#define  BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD	18	/* Regaddr shift (rev < 10) */
-+#define  BCMA_CORE_PCI_MDIODATA_REGADDR_MASK_OLD	0x003c0000 /* Regaddr Mask (rev < 10) */
-+#define  BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD	22	/* Physmedia devaddr shift (rev < 10) */
-+#define  BCMA_CORE_PCI_MDIODATA_DEVADDR_MASK_OLD	0x0fc00000 /* Physmedia devaddr Mask (rev < 10) */
-+#define  BCMA_CORE_PCI_MDIODATA_REGADDR_SHF	18	/* Regaddr shift */
-+#define  BCMA_CORE_PCI_MDIODATA_REGADDR_MASK	0x007c0000 /* Regaddr Mask */
-+#define  BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF	23	/* Physmedia devaddr shift */
-+#define  BCMA_CORE_PCI_MDIODATA_DEVADDR_MASK	0x0f800000 /* Physmedia devaddr Mask */
-+#define  BCMA_CORE_PCI_MDIODATA_WRITE		0x10000000 /* write Transaction */
-+#define  BCMA_CORE_PCI_MDIODATA_READ		0x20000000 /* Read Transaction */
-+#define  BCMA_CORE_PCI_MDIODATA_START		0x40000000 /* start of Transaction */
-+#define  BCMA_CORE_PCI_MDIODATA_DEV_ADDR	0x0	/* dev address for serdes */
-+#define  BCMA_CORE_PCI_MDIODATA_BLK_ADDR	0x1F	/* blk address for serdes */
-+#define  BCMA_CORE_PCI_MDIODATA_DEV_PLL		0x1d	/* SERDES PLL Dev */
-+#define  BCMA_CORE_PCI_MDIODATA_DEV_TX		0x1e	/* SERDES TX Dev */
-+#define  BCMA_CORE_PCI_MDIODATA_DEV_RX		0x1f	/* SERDES RX Dev */
-+#define BCMA_CORE_PCI_PCIEIND_ADDR		0x0130	/* indirect access to the internal register */
-+#define BCMA_CORE_PCI_PCIEIND_DATA		0x0134	/* Data to/from the internal regsiter */
-+#define BCMA_CORE_PCI_CLKREQENCTRL		0x0138	/*  >= rev 6, Clkreq rdma control */
-+#define BCMA_CORE_PCI_PCICFG0			0x0400	/* PCI config space 0 (rev >= 8) */
-+#define BCMA_CORE_PCI_PCICFG1			0x0500	/* PCI config space 1 (rev >= 8) */
-+#define BCMA_CORE_PCI_PCICFG2			0x0600	/* PCI config space 2 (rev >= 8) */
-+#define BCMA_CORE_PCI_PCICFG3			0x0700	/* PCI config space 3 (rev >= 8) */
-+#define BCMA_CORE_PCI_SPROM(wordoffset)		(0x0800 + ((wordoffset) * 2)) /* SPROM shadow area (72 bytes) */
++	bcma_scan_switch_core(bus, BCMA_ADDR_BASE);
 +
-+/* SBtoPCIx */
-+#define BCMA_CORE_PCI_SBTOPCI_MEM		0x00000000
-+#define BCMA_CORE_PCI_SBTOPCI_IO		0x00000001
-+#define BCMA_CORE_PCI_SBTOPCI_CFG0		0x00000002
-+#define BCMA_CORE_PCI_SBTOPCI_CFG1		0x00000003
-+#define BCMA_CORE_PCI_SBTOPCI_PREF		0x00000004 /* Prefetch enable */
-+#define BCMA_CORE_PCI_SBTOPCI_BURST		0x00000008 /* Burst enable */
-+#define BCMA_CORE_PCI_SBTOPCI_MRM		0x00000020 /* Memory Read Multiple */
-+#define BCMA_CORE_PCI_SBTOPCI_RC		0x00000030 /* Read Command mask (rev >= 11) */
-+#define  BCMA_CORE_PCI_SBTOPCI_RC_READ		0x00000000 /* Memory read */
-+#define  BCMA_CORE_PCI_SBTOPCI_RC_READL		0x00000010 /* Memory read line */
-+#define  BCMA_CORE_PCI_SBTOPCI_RC_READM		0x00000020 /* Memory read multiple */
++	tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID);
++	chipinfo->id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
++	chipinfo->rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
++	chipinfo->pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
++	pr_info("Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n",
++		chipinfo->id, chipinfo->rev, chipinfo->pkg);
 +
-+/* PCIE protocol PHY diagnostic registers */
-+#define BCMA_CORE_PCI_PLP_MODEREG		0x200	/* Mode */
-+#define BCMA_CORE_PCI_PLP_STATUSREG		0x204	/* Status */
-+#define  BCMA_CORE_PCI_PLP_POLARITYINV_STAT	0x10	/* Status reg PCIE_PLP_STATUSREG */
-+#define BCMA_CORE_PCI_PLP_LTSSMCTRLREG		0x208	/* LTSSM control */
-+#define BCMA_CORE_PCI_PLP_LTLINKNUMREG		0x20c	/* Link Training Link number */
-+#define BCMA_CORE_PCI_PLP_LTLANENUMREG		0x210	/* Link Training Lane number */
-+#define BCMA_CORE_PCI_PLP_LTNFTSREG		0x214	/* Link Training N_FTS */
-+#define BCMA_CORE_PCI_PLP_ATTNREG		0x218	/* Attention */
-+#define BCMA_CORE_PCI_PLP_ATTNMASKREG		0x21C	/* Attention Mask */
-+#define BCMA_CORE_PCI_PLP_RXERRCTR		0x220	/* Rx Error */
-+#define BCMA_CORE_PCI_PLP_RXFRMERRCTR		0x224	/* Rx Framing Error */
-+#define BCMA_CORE_PCI_PLP_RXERRTHRESHREG	0x228	/* Rx Error threshold */
-+#define BCMA_CORE_PCI_PLP_TESTCTRLREG		0x22C	/* Test Control reg */
-+#define BCMA_CORE_PCI_PLP_SERDESCTRLOVRDREG	0x230	/* SERDES Control Override */
-+#define BCMA_CORE_PCI_PLP_TIMINGOVRDREG		0x234	/* Timing param override */
-+#define BCMA_CORE_PCI_PLP_RXTXSMDIAGREG		0x238	/* RXTX State Machine Diag */
-+#define BCMA_CORE_PCI_PLP_LTSSMDIAGREG		0x23C	/* LTSSM State Machine Diag */
++	bus->init_done = true;
++}
 +
-+/* PCIE protocol DLLP diagnostic registers */
-+#define BCMA_CORE_PCI_DLLP_LCREG		0x100	/* Link Control */
-+#define BCMA_CORE_PCI_DLLP_LSREG		0x104	/* Link Status */
-+#define BCMA_CORE_PCI_DLLP_LAREG		0x108	/* Link Attention */
-+#define  BCMA_CORE_PCI_DLLP_LSREG_LINKUP	(1 << 16)
-+#define BCMA_CORE_PCI_DLLP_LAMASKREG		0x10C	/* Link Attention Mask */
-+#define BCMA_CORE_PCI_DLLP_NEXTTXSEQNUMREG	0x110	/* Next Tx Seq Num */
-+#define BCMA_CORE_PCI_DLLP_ACKEDTXSEQNUMREG	0x114	/* Acked Tx Seq Num */
-+#define BCMA_CORE_PCI_DLLP_PURGEDTXSEQNUMREG	0x118	/* Purged Tx Seq Num */
-+#define BCMA_CORE_PCI_DLLP_RXSEQNUMREG		0x11C	/* Rx Sequence Number */
-+#define BCMA_CORE_PCI_DLLP_LRREG		0x120	/* Link Replay */
-+#define BCMA_CORE_PCI_DLLP_LACKTOREG		0x124	/* Link Ack Timeout */
-+#define BCMA_CORE_PCI_DLLP_PMTHRESHREG		0x128	/* Power Management Threshold */
-+#define BCMA_CORE_PCI_DLLP_RTRYWPREG		0x12C	/* Retry buffer write ptr */
-+#define BCMA_CORE_PCI_DLLP_RTRYRPREG		0x130	/* Retry buffer Read ptr */
-+#define BCMA_CORE_PCI_DLLP_RTRYPPREG		0x134	/* Retry buffer Purged ptr */
-+#define BCMA_CORE_PCI_DLLP_RTRRWREG		0x138	/* Retry buffer Read/Write */
-+#define BCMA_CORE_PCI_DLLP_ECTHRESHREG		0x13C	/* Error Count Threshold */
-+#define BCMA_CORE_PCI_DLLP_TLPERRCTRREG		0x140	/* TLP Error Counter */
-+#define BCMA_CORE_PCI_DLLP_ERRCTRREG		0x144	/* Error Counter */
-+#define BCMA_CORE_PCI_DLLP_NAKRXCTRREG		0x148	/* NAK Received Counter */
-+#define BCMA_CORE_PCI_DLLP_TESTREG		0x14C	/* Test */
-+#define BCMA_CORE_PCI_DLLP_PKTBIST		0x150	/* Packet BIST */
-+#define BCMA_CORE_PCI_DLLP_PCIE11		0x154	/* DLLP PCIE 1.1 reg */
++int bcma_bus_scan(struct bcma_bus *bus)
++{
++	u32 erombase;
++	u32 __iomem *eromptr, *eromend;
 +
-+/* SERDES RX registers */
-+#define BCMA_CORE_PCI_SERDES_RX_CTRL		1	/* Rx cntrl */
-+#define  BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE	0x80	/* rxpolarity_force */
-+#define  BCMA_CORE_PCI_SERDES_RX_CTRL_POLARITY	0x40	/* rxpolarity_value */
-+#define BCMA_CORE_PCI_SERDES_RX_TIMER1		2	/* Rx Timer1 */
-+#define BCMA_CORE_PCI_SERDES_RX_CDR		6	/* CDR */
-+#define BCMA_CORE_PCI_SERDES_RX_CDRBW		7	/* CDR BW */
++	int err, core_num = 0;
 +
-+/* SERDES PLL registers */
-+#define BCMA_CORE_PCI_SERDES_PLL_CTRL		1	/* PLL control reg */
-+#define BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN	0x4000	/* bit 14 is FREQDET on */
++	bcma_init_bus(bus);
 +
-+/* PCIcore specific boardflags */
-+#define BCMA_CORE_PCI_BFL_NOPCI			0x00000400 /* Board leaves PCI floating */
++	erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
++	if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
++		eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
++		if (!eromptr)
++			return -ENOMEM;
++	} else {
++		eromptr = bus->mmio;
++	}
 +
-+/* PCIE Config space accessing MACROS */
-+#define BCMA_CORE_PCI_CFG_BUS_SHIFT		24	/* Bus shift */
-+#define BCMA_CORE_PCI_CFG_SLOT_SHIFT		19	/* Slot/Device shift */
-+#define BCMA_CORE_PCI_CFG_FUN_SHIFT		16	/* Function shift */
-+#define BCMA_CORE_PCI_CFG_OFF_SHIFT		0	/* Register shift */
++	eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
 +
-+#define BCMA_CORE_PCI_CFG_BUS_MASK		0xff	/* Bus mask */
-+#define BCMA_CORE_PCI_CFG_SLOT_MASK		0x1f	/* Slot/Device mask */
-+#define BCMA_CORE_PCI_CFG_FUN_MASK		7	/* Function mask */
-+#define BCMA_CORE_PCI_CFG_OFF_MASK		0xfff	/* Register mask */
++	bcma_scan_switch_core(bus, erombase);
 +
-+/* PCIE Root Capability Register bits (Host mode only) */
-+#define BCMA_CORE_PCI_RC_CRS_VISIBILITY		0x0001
++	while (eromptr < eromend) {
++		struct bcma_device *other_core;
++		struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL);
++		if (!core)
++			return -ENOMEM;
++		INIT_LIST_HEAD(&core->list);
++		core->bus = bus;
 +
-+struct bcma_drv_pci;
++		err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core);
++		if (err < 0) {
++			kfree(core);
++			if (err == -ENODEV) {
++				core_num++;
++				continue;
++			} else if (err == -ENXIO) {
++				continue;
++			} else if (err == -ESPIPE) {
++				break;
++			}
++			return err;
++		}
 +
-+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
-+struct bcma_drv_pci_host {
-+	struct bcma_drv_pci *pdev;
++		core->core_index = core_num++;
++		bus->nr_cores++;
++		other_core = bcma_find_core_reverse(bus, core->id.id);
++		core->core_unit = (other_core == NULL) ? 0 : other_core->core_unit + 1;
 +
-+	u32 host_cfg_addr;
-+	spinlock_t cfgspace_lock;
++		pr_info("Core %d found: %s "
++			"(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
++			core->core_index, bcma_device_name(&core->id),
++			core->id.manuf, core->id.id, core->id.rev,
++			core->id.class);
 +
-+	struct pci_controller pci_controller;
-+	struct pci_ops pci_ops;
-+	struct resource mem_resource;
-+	struct resource io_resource;
-+};
-+#endif
++		list_add(&core->list, &bus->cores);
++	}
 +
-+struct bcma_drv_pci {
-+	struct bcma_device *core;
-+	u8 setup_done:1;
-+	u8 hostmode:1;
++	if (bus->hosttype == BCMA_HOSTTYPE_SOC)
++		iounmap(eromptr);
 +
-+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
-+	struct bcma_drv_pci_host *host_controller;
-+#endif
-+};
++	return 0;
++}
 +
-+/* Register access */
-+#define pcicore_read32(pc, offset)		bcma_read32((pc)->core, offset)
-+#define pcicore_write32(pc, offset, val)	bcma_write32((pc)->core, offset, val)
++int __init bcma_bus_scan_early(struct bcma_bus *bus,
++			       struct bcma_device_id *match,
++			       struct bcma_device *core)
++{
++	u32 erombase;
++	u32 __iomem *eromptr, *eromend;
 +
-+extern void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc);
-+extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
-+				 struct bcma_device *core, bool enable);
++	int err = -ENODEV;
++	int core_num = 0;
 +
-+extern int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev);
-+extern int bcma_core_pci_plat_dev_init(struct pci_dev *dev);
++	erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
++	if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
++		eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
++		if (!eromptr)
++			return -ENOMEM;
++	} else {
++		eromptr = bus->mmio;
++	}
 +
-+#endif /* LINUX_BCMA_DRIVER_PCI_H_ */
---- /dev/null
-+++ b/include/linux/bcma/bcma_regs.h
-@@ -0,0 +1,86 @@
-+#ifndef LINUX_BCMA_REGS_H_
-+#define LINUX_BCMA_REGS_H_
++	eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
 +
-+/* Some single registers are shared between many cores */
-+/* BCMA_CLKCTLST: ChipCommon (rev >= 20), PCIe, 80211 */
-+#define BCMA_CLKCTLST			0x01E0 /* Clock control and status */
-+#define  BCMA_CLKCTLST_FORCEALP		0x00000001 /* Force ALP request */
-+#define  BCMA_CLKCTLST_FORCEHT		0x00000002 /* Force HT request */
-+#define  BCMA_CLKCTLST_FORCEILP		0x00000004 /* Force ILP request */
-+#define  BCMA_CLKCTLST_HAVEALPREQ	0x00000008 /* ALP available request */
-+#define  BCMA_CLKCTLST_HAVEHTREQ	0x00000010 /* HT available request */
-+#define  BCMA_CLKCTLST_HWCROFF		0x00000020 /* Force HW clock request off */
-+#define  BCMA_CLKCTLST_EXTRESREQ	0x00000700 /* Mask of external resource requests */
-+#define  BCMA_CLKCTLST_HAVEALP		0x00010000 /* ALP available */
-+#define  BCMA_CLKCTLST_HAVEHT		0x00020000 /* HT available */
-+#define  BCMA_CLKCTLST_BP_ON_ALP	0x00040000 /* RO: running on ALP clock */
-+#define  BCMA_CLKCTLST_BP_ON_HT		0x00080000 /* RO: running on HT clock */
-+#define  BCMA_CLKCTLST_EXTRESST		0x07000000 /* Mask of external resource status */
-+/* Is there any BCM4328 on BCMA bus? */
-+#define  BCMA_CLKCTLST_4328A0_HAVEHT	0x00010000 /* 4328a0 has reversed bits */
-+#define  BCMA_CLKCTLST_4328A0_HAVEALP	0x00020000 /* 4328a0 has reversed bits */
++	bcma_scan_switch_core(bus, erombase);
 +
-+/* Agent registers (common for every core) */
-+#define BCMA_IOCTL			0x0408 /* IO control */
-+#define  BCMA_IOCTL_CLK			0x0001
-+#define  BCMA_IOCTL_FGC			0x0002
-+#define  BCMA_IOCTL_CORE_BITS		0x3FFC
-+#define  BCMA_IOCTL_PME_EN		0x4000
-+#define  BCMA_IOCTL_BIST_EN		0x8000
-+#define BCMA_IOST			0x0500 /* IO status */
-+#define  BCMA_IOST_CORE_BITS		0x0FFF
-+#define  BCMA_IOST_DMA64		0x1000
-+#define  BCMA_IOST_GATED_CLK		0x2000
-+#define  BCMA_IOST_BIST_ERROR		0x4000
-+#define  BCMA_IOST_BIST_DONE		0x8000
-+#define BCMA_RESET_CTL			0x0800
-+#define  BCMA_RESET_CTL_RESET		0x0001
++	while (eromptr < eromend) {
++		memset(core, 0, sizeof(*core));
++		INIT_LIST_HEAD(&core->list);
++		core->bus = bus;
 +
-+/* BCMA PCI config space registers. */
-+#define BCMA_PCI_PMCSR			0x44
-+#define  BCMA_PCI_PE			0x100
-+#define BCMA_PCI_BAR0_WIN		0x80	/* Backplane address space 0 */
-+#define BCMA_PCI_BAR1_WIN		0x84	/* Backplane address space 1 */
-+#define BCMA_PCI_SPROMCTL		0x88	/* SPROM control */
-+#define  BCMA_PCI_SPROMCTL_WE		0x10	/* SPROM write enable */
-+#define BCMA_PCI_BAR1_CONTROL		0x8c	/* Address space 1 burst control */
-+#define BCMA_PCI_IRQS			0x90	/* PCI interrupts */
-+#define BCMA_PCI_IRQMASK		0x94	/* PCI IRQ control and mask (pcirev >= 6 only) */
-+#define BCMA_PCI_BACKPLANE_IRQS		0x98	/* Backplane Interrupts */
-+#define BCMA_PCI_BAR0_WIN2		0xAC
-+#define BCMA_PCI_GPIO_IN		0xB0	/* GPIO Input (pcirev >= 3 only) */
-+#define BCMA_PCI_GPIO_OUT		0xB4	/* GPIO Output (pcirev >= 3 only) */
-+#define BCMA_PCI_GPIO_OUT_ENABLE	0xB8	/* GPIO Output Enable/Disable (pcirev >= 3 only) */
-+#define  BCMA_PCI_GPIO_SCS		0x10	/* PCI config space bit 4 for 4306c0 slow clock source */
-+#define  BCMA_PCI_GPIO_HWRAD		0x20	/* PCI config space GPIO 13 for hw radio disable */
-+#define  BCMA_PCI_GPIO_XTAL		0x40	/* PCI config space GPIO 14 for Xtal powerup */
-+#define  BCMA_PCI_GPIO_PLL		0x80	/* PCI config space GPIO 15 for PLL powerdown */
++		err = bcma_get_next_core(bus, &eromptr, match, core_num, core);
++		if (err == -ENODEV) {
++			core_num++;
++			continue;
++		} else if (err == -ENXIO)
++			continue;
++		else if (err == -ESPIPE)
++			break;
++		else if (err < 0)
++			return err;
 +
-+/* SiliconBackplane Address Map.
-+ * All regions may not exist on all chips.
-+ */
-+#define BCMA_SOC_SDRAM_BASE		0x00000000U	/* Physical SDRAM */
-+#define BCMA_SOC_PCI_MEM		0x08000000U	/* Host Mode sb2pcitranslation0 (64 MB) */
-+#define BCMA_SOC_PCI_MEM_SZ		(64 * 1024 * 1024)
-+#define BCMA_SOC_PCI_CFG		0x0c000000U	/* Host Mode sb2pcitranslation1 (64 MB) */
-+#define BCMA_SOC_SDRAM_SWAPPED		0x10000000U	/* Byteswapped Physical SDRAM */
-+#define BCMA_SOC_SDRAM_R2		0x80000000U	/* Region 2 for sdram (512 MB) */
++		core->core_index = core_num++;
++		bus->nr_cores++;
++		pr_info("Core %d found: %s "
++			"(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
++			core->core_index, bcma_device_name(&core->id),
++			core->id.manuf, core->id.id, core->id.rev,
++			core->id.class);
 +
++		list_add(&core->list, &bus->cores);
++		err = 0;
++		break;
++	}
 +
-+#define BCMA_SOC_PCI_DMA		0x40000000U	/* Client Mode sb2pcitranslation2 (1 GB) */
-+#define BCMA_SOC_PCI_DMA2		0x80000000U	/* Client Mode sb2pcitranslation2 (1 GB) */
-+#define BCMA_SOC_PCI_DMA_SZ		0x40000000U	/* Client Mode sb2pcitranslation2 size in bytes */
-+#define BCMA_SOC_PCIE_DMA_L32		0x00000000U	/* PCIE Client Mode sb2pcitranslation2
-+							 * (2 ZettaBytes), low 32 bits
-+							 */
-+#define BCMA_SOC_PCIE_DMA_H32		0x80000000U	/* PCIE Client Mode sb2pcitranslation2
-+							 * (2 ZettaBytes), high 32 bits
-+							 */
++	if (bus->hosttype == BCMA_HOSTTYPE_SOC)
++		iounmap(eromptr);
 +
-+#define BCMA_SOC_PCI1_MEM		0x40000000U	/* Host Mode sb2pcitranslation0 (64 MB) */
-+#define BCMA_SOC_PCI1_CFG		0x44000000U	/* Host Mode sb2pcitranslation1 (64 MB) */
-+#define BCMA_SOC_PCIE1_DMA_H32		0xc0000000U	/* PCIE Client Mode sb2pcitranslation2
-+							 * (2 ZettaBytes), high 32 bits
-+							 */
++	return err;
++}
+--- /dev/null
++++ b/drivers/bcma/scan.h
+@@ -0,0 +1,56 @@
++#ifndef BCMA_SCAN_H_
++#define BCMA_SCAN_H_
 +
-+#endif /* LINUX_BCMA_REGS_H_ */
---- a/include/linux/mod_devicetable.h
-+++ b/include/linux/mod_devicetable.h
-@@ -382,6 +382,23 @@ struct ssb_device_id {
- #define SSB_ANY_ID		0xFFFF
- #define SSB_ANY_REV		0xFF
- 
-+/* Broadcom's specific AMBA core, see drivers/bcma/ */
-+struct bcma_device_id {
-+	__u16	manuf;
-+	__u16	id;
-+	__u8	rev;
-+	__u8	class;
-+};
-+#define BCMA_CORE(_manuf, _id, _rev, _class)  \
-+	{ .manuf = _manuf, .id = _id, .rev = _rev, .class = _class, }
-+#define BCMA_CORETABLE_END  \
-+	{ 0, },
++#define BCMA_ADDR_BASE		0x18000000
++#define BCMA_WRAP_BASE		0x18100000
 +
-+#define BCMA_ANY_MANUF		0xFFFF
-+#define BCMA_ANY_ID		0xFFFF
-+#define BCMA_ANY_REV		0xFF
-+#define BCMA_ANY_CLASS		0xFF
++#define SCAN_ER_VALID		0x00000001
++#define SCAN_ER_TAGX		0x00000006 /* we have to ignore 0x8 bit when checking tag for SCAN_ER_TAG_ADDR */
++#define SCAN_ER_TAG		0x0000000E
++#define  SCAN_ER_TAG_CI		0x00000000
++#define  SCAN_ER_TAG_MP		0x00000002
++#define  SCAN_ER_TAG_ADDR	0x00000004
++#define  SCAN_ER_TAG_END	0x0000000E
++#define SCAN_ER_BAD		0xFFFFFFFF
 +
- struct virtio_device_id {
- 	__u32 device;
- 	__u32 vendor;
---- a/scripts/mod/file2alias.c
-+++ b/scripts/mod/file2alias.c
-@@ -702,6 +702,24 @@ static int do_ssb_entry(const char *file
- 	return 1;
- }
- 
-+/* Looks like: bcma:mNidNrevNclN. */
-+static int do_bcma_entry(const char *filename,
-+			 struct bcma_device_id *id, char *alias)
-+{
-+	id->manuf = TO_NATIVE(id->manuf);
-+	id->id = TO_NATIVE(id->id);
-+	id->rev = TO_NATIVE(id->rev);
-+	id->class = TO_NATIVE(id->class);
++#define SCAN_CIA_CLASS		0x000000F0
++#define SCAN_CIA_CLASS_SHIFT	4
++#define SCAN_CIA_ID		0x000FFF00
++#define SCAN_CIA_ID_SHIFT	8
++#define SCAN_CIA_MANUF		0xFFF00000
++#define SCAN_CIA_MANUF_SHIFT	20
 +
-+	strcpy(alias, "bcma:");
-+	ADD(alias, "m", id->manuf != BCMA_ANY_MANUF, id->manuf);
-+	ADD(alias, "id", id->id != BCMA_ANY_ID, id->id);
-+	ADD(alias, "rev", id->rev != BCMA_ANY_REV, id->rev);
-+	ADD(alias, "cl", id->class != BCMA_ANY_CLASS, id->class);
-+	add_wildcard(alias);
-+	return 1;
-+}
++#define SCAN_CIB_NMP		0x000001F0
++#define SCAN_CIB_NMP_SHIFT	4
++#define SCAN_CIB_NSP		0x00003E00
++#define SCAN_CIB_NSP_SHIFT	9
++#define SCAN_CIB_NMW		0x0007C000
++#define SCAN_CIB_NMW_SHIFT	14
++#define SCAN_CIB_NSW		0x00F80000
++#define SCAN_CIB_NSW_SHIFT	17
++#define SCAN_CIB_REV		0xFF000000
++#define SCAN_CIB_REV_SHIFT	24
 +
- /* Looks like: virtio:dNvN */
- static int do_virtio_entry(const char *filename, struct virtio_device_id *id,
- 			   char *alias)
-@@ -968,6 +986,10 @@ void handle_moddevtable(struct module *m
- 		do_table(symval, sym->st_size,
- 			 sizeof(struct ssb_device_id), "ssb",
- 			 do_ssb_entry, mod);
-+	else if (sym_is(symname, "__mod_bcma_device_table"))
-+		do_table(symval, sym->st_size,
-+			 sizeof(struct bcma_device_id), "bcma",
-+			 do_bcma_entry, mod);
- 	else if (sym_is(symname, "__mod_virtio_device_table"))
- 		do_table(symval, sym->st_size,
- 			 sizeof(struct virtio_device_id), "virtio",
++#define SCAN_ADDR_AG32		0x00000008
++#define SCAN_ADDR_SZ		0x00000030
++#define SCAN_ADDR_SZ_SHIFT	4
++#define  SCAN_ADDR_SZ_4K	0x00000000
++#define  SCAN_ADDR_SZ_8K	0x00000010
++#define  SCAN_ADDR_SZ_16K	0x00000020
++#define  SCAN_ADDR_SZ_SZD	0x00000030
++#define SCAN_ADDR_TYPE		0x000000C0
++#define  SCAN_ADDR_TYPE_SLAVE	0x00000000
++#define  SCAN_ADDR_TYPE_BRIDGE	0x00000040
++#define  SCAN_ADDR_TYPE_SWRAP	0x00000080
++#define  SCAN_ADDR_TYPE_MWRAP	0x000000C0
++#define SCAN_ADDR_PORT		0x00000F00
++#define SCAN_ADDR_PORT_SHIFT	8
++#define SCAN_ADDR_ADDR		0xFFFFF000
++
++#define SCAN_ADDR_SZ_BASE	0x00001000	/* 4KB */
++
++#define SCAN_SIZE_SZ_ALIGN	0x00000FFF
++#define SCAN_SIZE_SZ		0xFFFFF000
++#define SCAN_SIZE_SG32		0x00000008
++
++#endif /* BCMA_SCAN_H_ */
 --- /dev/null
 +++ b/drivers/bcma/sprom.c
-@@ -0,0 +1,450 @@
+@@ -0,0 +1,600 @@
 +/*
 + * Broadcom specific AMBA
 + * SPROM reading
@@ -3599,6 +3616,22 @@
 +#define SPEX(_field, _offset, _mask, _shift)	\
 +	bus->sprom._field = ((sprom[SPOFF(_offset)] & (_mask)) >> (_shift))
 +
++#define SPEX32(_field, _offset, _mask, _shift)	\
++	bus->sprom._field = ((((u32)sprom[SPOFF((_offset)+2)] << 16 | \
++				sprom[SPOFF(_offset)]) & (_mask)) >> (_shift))
++
++#define SPEX_ARRAY8(_field, _offset, _mask, _shift)	\
++	do {	\
++		SPEX(_field[0], _offset +  0, _mask, _shift);	\
++		SPEX(_field[1], _offset +  2, _mask, _shift);	\
++		SPEX(_field[2], _offset +  4, _mask, _shift);	\
++		SPEX(_field[3], _offset +  6, _mask, _shift);	\
++		SPEX(_field[4], _offset +  8, _mask, _shift);	\
++		SPEX(_field[5], _offset + 10, _mask, _shift);	\
++		SPEX(_field[6], _offset + 12, _mask, _shift);	\
++		SPEX(_field[7], _offset + 14, _mask, _shift);	\
++	} while (0)
++
 +static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
 +{
 +	u16 v, o;
@@ -3661,7 +3694,8 @@
 +	SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, ~0, 0);
 +	SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, ~0, 0);
 +
-+	SPEX(country_code, SSB_SPROM8_CCODE, ~0, 0);
++	SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
++	SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
 +
 +	/* Extract cores power info info */
 +	for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
@@ -3692,1271 +3726,1419 @@
 +		SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
 +		SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
 +		SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
-+		SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
-+	}
-+
-+	SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TSSIPOS,
-+	     SSB_SROM8_FEM_TSSIPOS_SHIFT);
-+	SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_EXTPA_GAIN,
-+	     SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
-+	SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_PDET_RANGE,
-+	     SSB_SROM8_FEM_PDET_RANGE_SHIFT);
-+	SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TR_ISO,
-+	     SSB_SROM8_FEM_TR_ISO_SHIFT);
-+	SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_ANTSWLUT,
-+	     SSB_SROM8_FEM_ANTSWLUT_SHIFT);
-+
-+	SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TSSIPOS,
-+	     SSB_SROM8_FEM_TSSIPOS_SHIFT);
-+	SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_EXTPA_GAIN,
-+	     SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
-+	SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_PDET_RANGE,
-+	     SSB_SROM8_FEM_PDET_RANGE_SHIFT);
-+	SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TR_ISO,
-+	     SSB_SROM8_FEM_TR_ISO_SHIFT);
-+	SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT,
-+	     SSB_SROM8_FEM_ANTSWLUT_SHIFT);
-+}
-+
-+/*
-+ * Indicates the presence of external SPROM.
-+ */
-+static bool bcma_sprom_ext_available(struct bcma_bus *bus)
-+{
-+	u32 chip_status;
-+	u32 srom_control;
-+	u32 present_mask;
-+
-+	if (bus->drv_cc.core->id.rev >= 31) {
-+		if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
-+			return false;
-+
-+		srom_control = bcma_read32(bus->drv_cc.core,
-+					   BCMA_CC_SROM_CONTROL);
-+		return srom_control & BCMA_CC_SROM_CONTROL_PRESENT;
-+	}
-+
-+	/* older chipcommon revisions use chip status register */
-+	chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
-+	switch (bus->chipinfo.id) {
-+	case 0x4313:
-+		present_mask = BCMA_CC_CHIPST_4313_SPROM_PRESENT;
-+		break;
-+
-+	case 0x4331:
-+		present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT;
-+		break;
-+
-+	default:
-+		return true;
-+	}
-+
-+	return chip_status & present_mask;
-+}
-+
-+/*
-+ * Indicates that on-chip OTP memory is present and enabled.
-+ */
-+static bool bcma_sprom_onchip_available(struct bcma_bus *bus)
-+{
-+	u32 chip_status;
-+	u32 otpsize = 0;
-+	bool present;
-+
-+	chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
-+	switch (bus->chipinfo.id) {
-+	case 0x4313:
-+		present = chip_status & BCMA_CC_CHIPST_4313_OTP_PRESENT;
-+		break;
-+
-+	case 0x4331:
-+		present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT;
-+		break;
-+
-+	case 43224:
-+	case 43225:
-+		/* for these chips OTP is always available */
-+		present = true;
-+		break;
-+
-+	default:
-+		present = false;
-+		break;
-+	}
-+
-+	if (present) {
-+		otpsize = bus->drv_cc.capabilities & BCMA_CC_CAP_OTPS;
-+		otpsize >>= BCMA_CC_CAP_OTPS_SHIFT;
-+	}
-+
-+	return otpsize != 0;
-+}
-+
-+/*
-+ * Verify OTP is filled and determine the byte
-+ * offset where SPROM data is located.
-+ *
-+ * On error, returns 0; byte offset otherwise.
-+ */
-+static int bcma_sprom_onchip_offset(struct bcma_bus *bus)
-+{
-+	struct bcma_device *cc = bus->drv_cc.core;
-+	u32 offset;
-+
-+	/* verify OTP status */
-+	if ((bcma_read32(cc, BCMA_CC_OTPS) & BCMA_CC_OTPS_GU_PROG_HW) == 0)
-+		return 0;
-+
-+	/* obtain bit offset from otplayout register */
-+	offset = (bcma_read32(cc, BCMA_CC_OTPL) & BCMA_CC_OTPL_GURGN_OFFSET);
-+	return BCMA_CC_SPROM + (offset >> 3);
-+}
-+
-+int bcma_sprom_get(struct bcma_bus *bus)
-+{
-+	u16 offset = BCMA_CC_SPROM;
-+	u16 *sprom;
-+	int err = 0;
-+
-+	if (!bus->drv_cc.core)
-+		return -EOPNOTSUPP;
-+
-+	if (!bcma_sprom_ext_available(bus)) {
-+		/*
-+		 * External SPROM takes precedence so check
-+		 * on-chip OTP only when no external SPROM
-+		 * is present.
-+		 */
-+		if (bcma_sprom_onchip_available(bus)) {
-+			/* determine offset */
-+			offset = bcma_sprom_onchip_offset(bus);
-+		}
-+		if (!offset) {
-+			/*
-+			 * Maybe there is no SPROM on the device?
-+			 * Now we ask the arch code if there is some sprom
-+			 * available for this device in some other storage.
-+			 */
-+			err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
-+			return err;
-+		}
-+	}
-+
-+	sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
-+			GFP_KERNEL);
-+	if (!sprom)
-+		return -ENOMEM;
-+
-+	if (bus->chipinfo.id == 0x4331)
-+		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
-+
-+	pr_debug("SPROM offset 0x%x\n", offset);
-+	bcma_sprom_read(bus, offset, sprom);
-+
-+	if (bus->chipinfo.id == 0x4331)
-+		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
-+
-+	err = bcma_sprom_valid(sprom);
-+	if (err)
-+		goto out;
-+
-+	bcma_sprom_extract_r8(bus, sprom);
-+
-+out:
-+	kfree(sprom);
-+	return err;
-+}
---- /dev/null
-+++ b/drivers/bcma/driver_pci_host.c
-@@ -0,0 +1,589 @@
-+/*
-+ * Broadcom specific AMBA
-+ * PCI Core in hostmode
-+ *
-+ * Copyright 2005 - 2011, Broadcom Corporation
-+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
-+ * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
-+ *
-+ * Licensed under the GNU/GPL. See COPYING for details.
-+ */
-+
-+#include "bcma_private.h"
-+#include <linux/pci.h>
-+#include <linux/export.h>
-+#include <linux/bcma/bcma.h>
-+#include <asm/paccess.h>
-+
-+/* Probe a 32bit value on the bus and catch bus exceptions.
-+ * Returns nonzero on a bus exception.
-+ * This is MIPS specific */
-+#define mips_busprobe32(val, addr)	get_dbe((val), ((u32 *)(addr)))
-+
-+/* Assume one-hot slot wiring */
-+#define BCMA_PCI_SLOT_MAX	16
-+#define	PCI_CONFIG_SPACE_SIZE	256
-+
-+bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
-+{
-+	struct bcma_bus *bus = pc->core->bus;
-+	u16 chipid_top;
-+	u32 tmp;
-+
-+	chipid_top = (bus->chipinfo.id & 0xFF00);
-+	if (chipid_top != 0x4700 &&
-+	    chipid_top != 0x5300)
-+		return false;
-+
-+	if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
-+		pr_info("This PCI core is disabled and not working\n");
-+		return false;
-+	}
-+
-+	bcma_core_enable(pc->core, 0);
-+
-+	return !mips_busprobe32(tmp, pc->core->io_addr);
-+}
-+
-+static u32 bcma_pcie_read_config(struct bcma_drv_pci *pc, u32 address)
-+{
-+	pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_ADDR, address);
-+	pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_ADDR);
-+	return pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_DATA);
-+}
-+
-+static void bcma_pcie_write_config(struct bcma_drv_pci *pc, u32 address,
-+				   u32 data)
-+{
-+	pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_ADDR, address);
-+	pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_ADDR);
-+	pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_DATA, data);
-+}
-+
-+static u32 bcma_get_cfgspace_addr(struct bcma_drv_pci *pc, unsigned int dev,
-+			     unsigned int func, unsigned int off)
-+{
-+	u32 addr = 0;
-+
-+	/* Issue config commands only when the data link is up (atleast
-+	 * one external pcie device is present).
-+	 */
-+	if (dev >= 2 || !(bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_LSREG)
-+			  & BCMA_CORE_PCI_DLLP_LSREG_LINKUP))
-+		goto out;
++		SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
++	}
 +
-+	/* Type 0 transaction */
-+	/* Slide the PCI window to the appropriate slot */
-+	pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0);
-+	/* Calculate the address */
-+	addr = pc->host_controller->host_cfg_addr;
-+	addr |= (dev << BCMA_CORE_PCI_CFG_SLOT_SHIFT);
-+	addr |= (func << BCMA_CORE_PCI_CFG_FUN_SHIFT);
-+	addr |= (off & ~3);
++	SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TSSIPOS,
++	     SSB_SROM8_FEM_TSSIPOS_SHIFT);
++	SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_EXTPA_GAIN,
++	     SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
++	SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_PDET_RANGE,
++	     SSB_SROM8_FEM_PDET_RANGE_SHIFT);
++	SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TR_ISO,
++	     SSB_SROM8_FEM_TR_ISO_SHIFT);
++	SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_ANTSWLUT,
++	     SSB_SROM8_FEM_ANTSWLUT_SHIFT);
 +
-+out:
-+	return addr;
++	SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TSSIPOS,
++	     SSB_SROM8_FEM_TSSIPOS_SHIFT);
++	SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_EXTPA_GAIN,
++	     SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
++	SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_PDET_RANGE,
++	     SSB_SROM8_FEM_PDET_RANGE_SHIFT);
++	SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TR_ISO,
++	     SSB_SROM8_FEM_TR_ISO_SHIFT);
++	SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT,
++	     SSB_SROM8_FEM_ANTSWLUT_SHIFT);
++
++	SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
++	     SSB_SPROM8_ANTAVAIL_A_SHIFT);
++	SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
++	     SSB_SPROM8_ANTAVAIL_BG_SHIFT);
++	SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
++	SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
++	     SSB_SPROM8_ITSSI_BG_SHIFT);
++	SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
++	SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
++	     SSB_SPROM8_ITSSI_A_SHIFT);
++	SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
++	SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
++	     SSB_SPROM8_MAXP_AL_SHIFT);
++	SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
++	SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
++	     SSB_SPROM8_GPIOA_P1_SHIFT);
++	SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
++	SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
++	     SSB_SPROM8_GPIOB_P3_SHIFT);
++	SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
++	SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
++	     SSB_SPROM8_TRI5G_SHIFT);
++	SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
++	SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
++	     SSB_SPROM8_TRI5GH_SHIFT);
++	SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G,
++	     SSB_SPROM8_RXPO2G_SHIFT);
++	SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
++	     SSB_SPROM8_RXPO5G_SHIFT);
++	SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
++	SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
++	     SSB_SPROM8_RSSISMC2G_SHIFT);
++	SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
++	     SSB_SPROM8_RSSISAV2G_SHIFT);
++	SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
++	     SSB_SPROM8_BXA2G_SHIFT);
++	SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
++	SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
++	     SSB_SPROM8_RSSISMC5G_SHIFT);
++	SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
++	     SSB_SPROM8_RSSISAV5G_SHIFT);
++	SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
++	     SSB_SPROM8_BXA5G_SHIFT);
++
++	SPEX(pa0b0, SSB_SPROM8_PA0B0, ~0, 0);
++	SPEX(pa0b1, SSB_SPROM8_PA0B1, ~0, 0);
++	SPEX(pa0b2, SSB_SPROM8_PA0B2, ~0, 0);
++	SPEX(pa1b0, SSB_SPROM8_PA1B0, ~0, 0);
++	SPEX(pa1b1, SSB_SPROM8_PA1B1, ~0, 0);
++	SPEX(pa1b2, SSB_SPROM8_PA1B2, ~0, 0);
++	SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, ~0, 0);
++	SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, ~0, 0);
++	SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, ~0, 0);
++	SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, ~0, 0);
++	SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, ~0, 0);
++	SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, ~0, 0);
++	SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, ~0, 0);
++	SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, ~0, 0);
++	SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, ~0, 0);
++	SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, ~0, 0);
++	SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0);
++
++	/* Extract the antenna gain values. */
++	SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
++	     SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
++	SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
++	     SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
++	SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
++	     SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
++	SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
++	     SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
++
++	SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
++	     SSB_SPROM8_LEDDC_ON_SHIFT);
++	SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
++	     SSB_SPROM8_LEDDC_OFF_SHIFT);
++
++	SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
++	     SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
++	SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
++	     SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
++	SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
++	     SSB_SPROM8_TXRXC_SWITCH_SHIFT);
++
++	SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
++
++	SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
++
++	SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
++	     SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
++	SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
++	     SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
++	SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
++	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
++	SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
++	SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
++	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
++	SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
++	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
++	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
++	SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
++	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
++	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
++	SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
++	     SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
++
++	SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
++	SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
++	SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
++	SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
++
++	SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
++	     SSB_SPROM8_THERMAL_TRESH_SHIFT);
++	SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
++	     SSB_SPROM8_THERMAL_OFFSET_SHIFT);
++	SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
++	     SSB_SPROM8_TEMPDELTA_PHYCAL,
++	     SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
++	SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
++	     SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
++	SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
++	     SSB_SPROM8_TEMPDELTA_HYSTERESIS,
++	     SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
 +}
 +
-+static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev,
-+				  unsigned int func, unsigned int off,
-+				  void *buf, int len)
++/*
++ * Indicates the presence of external SPROM.
++ */
++static bool bcma_sprom_ext_available(struct bcma_bus *bus)
 +{
-+	int err = -EINVAL;
-+	u32 addr, val;
-+	void __iomem *mmio = 0;
-+
-+	WARN_ON(!pc->hostmode);
-+	if (unlikely(len != 1 && len != 2 && len != 4))
-+		goto out;
-+	if (dev == 0) {
-+		/* we support only two functions on device 0 */
-+		if (func > 1)
-+			return -EINVAL;
-+
-+		/* accesses to config registers with offsets >= 256
-+		 * requires indirect access.
-+		 */
-+		if (off >= PCI_CONFIG_SPACE_SIZE) {
-+			addr = (func << 12);
-+			addr |= (off & 0x0FFF);
-+			val = bcma_pcie_read_config(pc, addr);
-+		} else {
-+			addr = BCMA_CORE_PCI_PCICFG0;
-+			addr |= (func << 8);
-+			addr |= (off & 0xfc);
-+			val = pcicore_read32(pc, addr);
-+		}
-+	} else {
-+		addr = bcma_get_cfgspace_addr(pc, dev, func, off);
-+		if (unlikely(!addr))
-+			goto out;
-+		err = -ENOMEM;
-+		mmio = ioremap_nocache(addr, len);
-+		if (!mmio)
-+			goto out;
++	u32 chip_status;
++	u32 srom_control;
++	u32 present_mask;
 +
-+		if (mips_busprobe32(val, mmio)) {
-+			val = 0xffffffff;
-+			goto unmap;
-+		}
++	if (bus->drv_cc.core->id.rev >= 31) {
++		if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
++			return false;
 +
-+		val = readl(mmio);
++		srom_control = bcma_read32(bus->drv_cc.core,
++					   BCMA_CC_SROM_CONTROL);
++		return srom_control & BCMA_CC_SROM_CONTROL_PRESENT;
 +	}
-+	val >>= (8 * (off & 3));
 +
-+	switch (len) {
-+	case 1:
-+		*((u8 *)buf) = (u8)val;
-+		break;
-+	case 2:
-+		*((u16 *)buf) = (u16)val;
++	/* older chipcommon revisions use chip status register */
++	chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
++	switch (bus->chipinfo.id) {
++	case 0x4313:
++		present_mask = BCMA_CC_CHIPST_4313_SPROM_PRESENT;
 +		break;
-+	case 4:
-+		*((u32 *)buf) = (u32)val;
++
++	case 0x4331:
++		present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT;
 +		break;
++
++	default:
++		return true;
 +	}
-+	err = 0;
-+unmap:
-+	if (mmio)
-+		iounmap(mmio);
-+out:
-+	return err;
++
++	return chip_status & present_mask;
 +}
 +
-+static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev,
-+				   unsigned int func, unsigned int off,
-+				   const void *buf, int len)
++/*
++ * Indicates that on-chip OTP memory is present and enabled.
++ */
++static bool bcma_sprom_onchip_available(struct bcma_bus *bus)
 +{
-+	int err = -EINVAL;
-+	u32 addr = 0, val = 0;
-+	void __iomem *mmio = 0;
-+	u16 chipid = pc->core->bus->chipinfo.id;
-+
-+	WARN_ON(!pc->hostmode);
-+	if (unlikely(len != 1 && len != 2 && len != 4))
-+		goto out;
-+	if (dev == 0) {
-+		/* accesses to config registers with offsets >= 256
-+		 * requires indirect access.
-+		 */
-+		if (off < PCI_CONFIG_SPACE_SIZE) {
-+			addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0;
-+			addr |= (func << 8);
-+			addr |= (off & 0xfc);
-+			mmio = ioremap_nocache(addr, len);
-+			if (!mmio)
-+				goto out;
-+		}
-+	} else {
-+		addr = bcma_get_cfgspace_addr(pc, dev, func, off);
-+		if (unlikely(!addr))
-+			goto out;
-+		err = -ENOMEM;
-+		mmio = ioremap_nocache(addr, len);
-+		if (!mmio)
-+			goto out;
++	u32 chip_status;
++	u32 otpsize = 0;
++	bool present;
 +
-+		if (mips_busprobe32(val, mmio)) {
-+			val = 0xffffffff;
-+			goto unmap;
-+		}
-+	}
++	chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
++	switch (bus->chipinfo.id) {
++	case 0x4313:
++		present = chip_status & BCMA_CC_CHIPST_4313_OTP_PRESENT;
++		break;
 +
-+	switch (len) {
-+	case 1:
-+		val = readl(mmio);
-+		val &= ~(0xFF << (8 * (off & 3)));
-+		val |= *((const u8 *)buf) << (8 * (off & 3));
++	case 0x4331:
++		present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT;
 +		break;
-+	case 2:
-+		val = readl(mmio);
-+		val &= ~(0xFFFF << (8 * (off & 3)));
-+		val |= *((const u16 *)buf) << (8 * (off & 3));
++
++	case 43224:
++	case 43225:
++		/* for these chips OTP is always available */
++		present = true;
 +		break;
-+	case 4:
-+		val = *((const u32 *)buf);
++
++	default:
++		present = false;
 +		break;
 +	}
-+	if (dev == 0 && !addr) {
-+		/* accesses to config registers with offsets >= 256
-+		 * requires indirect access.
-+		 */
-+		addr = (func << 12);
-+		addr |= (off & 0x0FFF);
-+		bcma_pcie_write_config(pc, addr, val);
-+	} else {
-+		writel(val, mmio);
 +
-+		if (chipid == 0x4716 || chipid == 0x4748)
-+			readl(mmio);
++	if (present) {
++		otpsize = bus->drv_cc.capabilities & BCMA_CC_CAP_OTPS;
++		otpsize >>= BCMA_CC_CAP_OTPS_SHIFT;
 +	}
 +
-+	err = 0;
-+unmap:
-+	if (mmio)
-+		iounmap(mmio);
-+out:
-+	return err;
++	return otpsize != 0;
 +}
 +
-+static int bcma_core_pci_hostmode_read_config(struct pci_bus *bus,
-+					      unsigned int devfn,
-+					      int reg, int size, u32 *val)
++/*
++ * Verify OTP is filled and determine the byte
++ * offset where SPROM data is located.
++ *
++ * On error, returns 0; byte offset otherwise.
++ */
++static int bcma_sprom_onchip_offset(struct bcma_bus *bus)
 +{
-+	unsigned long flags;
-+	int err;
-+	struct bcma_drv_pci *pc;
-+	struct bcma_drv_pci_host *pc_host;
++	struct bcma_device *cc = bus->drv_cc.core;
++	u32 offset;
++
++	/* verify OTP status */
++	if ((bcma_read32(cc, BCMA_CC_OTPS) & BCMA_CC_OTPS_GU_PROG_HW) == 0)
++		return 0;
++
++	/* obtain bit offset from otplayout register */
++	offset = (bcma_read32(cc, BCMA_CC_OTPL) & BCMA_CC_OTPL_GURGN_OFFSET);
++	return BCMA_CC_SPROM + (offset >> 3);
++}
++
++int bcma_sprom_get(struct bcma_bus *bus)
++{
++	u16 offset = BCMA_CC_SPROM;
++	u16 *sprom;
++	int err = 0;
++
++	if (!bus->drv_cc.core)
++		return -EOPNOTSUPP;
++
++	if (!bcma_sprom_ext_available(bus)) {
++		bool sprom_onchip;
++
++		/*
++		 * External SPROM takes precedence so check
++		 * on-chip OTP only when no external SPROM
++		 * is present.
++		 */
++		sprom_onchip = bcma_sprom_onchip_available(bus);
++		if (sprom_onchip) {
++			/* determine offset */
++			offset = bcma_sprom_onchip_offset(bus);
++		}
++		if (!offset || !sprom_onchip) {
++			/*
++			 * Maybe there is no SPROM on the device?
++			 * Now we ask the arch code if there is some sprom
++			 * available for this device in some other storage.
++			 */
++			err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
++			return err;
++		}
++	}
 +
-+	pc_host = container_of(bus->ops, struct bcma_drv_pci_host, pci_ops);
-+	pc = pc_host->pdev;
++	sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
++			GFP_KERNEL);
++	if (!sprom)
++		return -ENOMEM;
 +
-+	spin_lock_irqsave(&pc_host->cfgspace_lock, flags);
-+	err = bcma_extpci_read_config(pc, PCI_SLOT(devfn),
-+				     PCI_FUNC(devfn), reg, val, size);
-+	spin_unlock_irqrestore(&pc_host->cfgspace_lock, flags);
++	if (bus->chipinfo.id == 0x4331)
++		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
 +
-+	return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
-+}
++	pr_debug("SPROM offset 0x%x\n", offset);
++	bcma_sprom_read(bus, offset, sprom);
 +
-+static int bcma_core_pci_hostmode_write_config(struct pci_bus *bus,
-+					       unsigned int devfn,
-+					       int reg, int size, u32 val)
-+{
-+	unsigned long flags;
-+	int err;
-+	struct bcma_drv_pci *pc;
-+	struct bcma_drv_pci_host *pc_host;
++	if (bus->chipinfo.id == 0x4331)
++		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
 +
-+	pc_host = container_of(bus->ops, struct bcma_drv_pci_host, pci_ops);
-+	pc = pc_host->pdev;
++	err = bcma_sprom_valid(sprom);
++	if (err)
++		goto out;
 +
-+	spin_lock_irqsave(&pc_host->cfgspace_lock, flags);
-+	err = bcma_extpci_write_config(pc, PCI_SLOT(devfn),
-+				      PCI_FUNC(devfn), reg, &val, size);
-+	spin_unlock_irqrestore(&pc_host->cfgspace_lock, flags);
++	bcma_sprom_extract_r8(bus, sprom);
 +
-+	return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
++out:
++	kfree(sprom);
++	return err;
 +}
+--- /dev/null
++++ b/include/linux/bcma/bcma.h
+@@ -0,0 +1,314 @@
++#ifndef LINUX_BCMA_H_
++#define LINUX_BCMA_H_
 +
-+/* return cap_offset if requested capability exists in the PCI config space */
-+static u8 __devinit bcma_find_pci_capability(struct bcma_drv_pci *pc,
-+					     unsigned int dev,
-+					     unsigned int func, u8 req_cap_id,
-+					     unsigned char *buf, u32 *buflen)
-+{
-+	u8 cap_id;
-+	u8 cap_ptr = 0;
-+	u32 bufsize;
-+	u8 byte_val;
-+
-+	/* check for Header type 0 */
-+	bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val,
-+				sizeof(u8));
-+	if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL)
-+		return cap_ptr;
++#include <linux/pci.h>
++#include <linux/mod_devicetable.h>
 +
-+	/* check if the capability pointer field exists */
-+	bcma_extpci_read_config(pc, dev, func, PCI_STATUS, &byte_val,
-+				sizeof(u8));
-+	if (!(byte_val & PCI_STATUS_CAP_LIST))
-+		return cap_ptr;
++#include <linux/bcma/bcma_driver_chipcommon.h>
++#include <linux/bcma/bcma_driver_pci.h>
++#include <linux/bcma/bcma_driver_mips.h>
++#include <linux/ssb/ssb.h> /* SPROM sharing */
 +
-+	/* check if the capability pointer is 0x00 */
-+	bcma_extpci_read_config(pc, dev, func, PCI_CAPABILITY_LIST, &cap_ptr,
-+				sizeof(u8));
-+	if (cap_ptr == 0x00)
-+		return cap_ptr;
++#include "bcma_regs.h"
 +
-+	/* loop thr'u the capability list and see if the requested capabilty
-+	 * exists */
-+	bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id, sizeof(u8));
-+	while (cap_id != req_cap_id) {
-+		bcma_extpci_read_config(pc, dev, func, cap_ptr + 1, &cap_ptr,
-+					sizeof(u8));
-+		if (cap_ptr == 0x00)
-+			return cap_ptr;
-+		bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id,
-+					sizeof(u8));
-+	}
++struct bcma_device;
++struct bcma_bus;
 +
-+	/* found the caller requested capability */
-+	if ((buf != NULL) && (buflen != NULL)) {
-+		u8 cap_data;
++enum bcma_hosttype {
++	BCMA_HOSTTYPE_PCI,
++	BCMA_HOSTTYPE_SDIO,
++	BCMA_HOSTTYPE_SOC,
++};
 +
-+		bufsize = *buflen;
-+		if (!bufsize)
-+			return cap_ptr;
++struct bcma_chipinfo {
++	u16 id;
++	u8 rev;
++	u8 pkg;
++};
 +
-+		*buflen = 0;
++struct bcma_boardinfo {
++	u16 vendor;
++	u16 type;
++};
 +
-+		/* copy the cpability data excluding cap ID and next ptr */
-+		cap_data = cap_ptr + 2;
-+		if ((bufsize + cap_data)  > PCI_CONFIG_SPACE_SIZE)
-+			bufsize = PCI_CONFIG_SPACE_SIZE - cap_data;
-+		*buflen = bufsize;
-+		while (bufsize--) {
-+			bcma_extpci_read_config(pc, dev, func, cap_data, buf,
-+						sizeof(u8));
-+			cap_data++;
-+			buf++;
-+		}
-+	}
++enum bcma_clkmode {
++	BCMA_CLKMODE_FAST,
++	BCMA_CLKMODE_DYNAMIC,
++};
 +
-+	return cap_ptr;
-+}
++struct bcma_host_ops {
++	u8 (*read8)(struct bcma_device *core, u16 offset);
++	u16 (*read16)(struct bcma_device *core, u16 offset);
++	u32 (*read32)(struct bcma_device *core, u16 offset);
++	void (*write8)(struct bcma_device *core, u16 offset, u8 value);
++	void (*write16)(struct bcma_device *core, u16 offset, u16 value);
++	void (*write32)(struct bcma_device *core, u16 offset, u32 value);
++#ifdef CONFIG_BCMA_BLOCKIO
++	void (*block_read)(struct bcma_device *core, void *buffer,
++			   size_t count, u16 offset, u8 reg_width);
++	void (*block_write)(struct bcma_device *core, const void *buffer,
++			    size_t count, u16 offset, u8 reg_width);
++#endif
++	/* Agent ops */
++	u32 (*aread32)(struct bcma_device *core, u16 offset);
++	void (*awrite32)(struct bcma_device *core, u16 offset, u32 value);
++};
 +
-+/* If the root port is capable of returning Config Request
-+ * Retry Status (CRS) Completion Status to software then
-+ * enable the feature.
-+ */
-+static void __devinit bcma_core_pci_enable_crs(struct bcma_drv_pci *pc)
-+{
-+	u8 cap_ptr, root_ctrl, root_cap, dev;
-+	u16 val16;
-+	int i;
++/* Core manufacturers */
++#define BCMA_MANUF_ARM			0x43B
++#define BCMA_MANUF_MIPS			0x4A7
++#define BCMA_MANUF_BCM			0x4BF
 +
-+	cap_ptr = bcma_find_pci_capability(pc, 0, 0, PCI_CAP_ID_EXP, NULL,
-+					   NULL);
-+	root_cap = cap_ptr + PCI_EXP_RTCAP;
-+	bcma_extpci_read_config(pc, 0, 0, root_cap, &val16, sizeof(u16));
-+	if (val16 & BCMA_CORE_PCI_RC_CRS_VISIBILITY) {
-+		/* Enable CRS software visibility */
-+		root_ctrl = cap_ptr + PCI_EXP_RTCTL;
-+		val16 = PCI_EXP_RTCTL_CRSSVE;
-+		bcma_extpci_read_config(pc, 0, 0, root_ctrl, &val16,
-+					sizeof(u16));
++/* Core class values. */
++#define BCMA_CL_SIM			0x0
++#define BCMA_CL_EROM			0x1
++#define BCMA_CL_CORESIGHT		0x9
++#define BCMA_CL_VERIF			0xB
++#define BCMA_CL_OPTIMO			0xD
++#define BCMA_CL_GEN			0xE
++#define BCMA_CL_PRIMECELL		0xF
 +
-+		/* Initiate a configuration request to read the vendor id
-+		 * field of the device function's config space header after
-+		 * 100 ms wait time from the end of Reset. If the device is
-+		 * not done with its internal initialization, it must at
-+		 * least return a completion TLP, with a completion status
-+		 * of "Configuration Request Retry Status (CRS)". The root
-+		 * complex must complete the request to the host by returning
-+		 * a read-data value of 0001h for the Vendor ID field and
-+		 * all 1s for any additional bytes included in the request.
-+		 * Poll using the config reads for max wait time of 1 sec or
-+		 * until we receive the successful completion status. Repeat
-+		 * the procedure for all the devices.
-+		 */
-+		for (dev = 1; dev < BCMA_PCI_SLOT_MAX; dev++) {
-+			for (i = 0; i < 100000; i++) {
-+				bcma_extpci_read_config(pc, dev, 0,
-+							PCI_VENDOR_ID, &val16,
-+							sizeof(val16));
-+				if (val16 != 0x1)
-+					break;
-+				udelay(10);
-+			}
-+			if (val16 == 0x1)
-+				pr_err("PCI: Broken device in slot %d\n", dev);
-+		}
-+	}
-+}
++/* Core-ID values. */
++#define BCMA_CORE_OOB_ROUTER		0x367	/* Out of band */
++#define BCMA_CORE_INVALID		0x700
++#define BCMA_CORE_CHIPCOMMON		0x800
++#define BCMA_CORE_ILINE20		0x801
++#define BCMA_CORE_SRAM			0x802
++#define BCMA_CORE_SDRAM			0x803
++#define BCMA_CORE_PCI			0x804
++#define BCMA_CORE_MIPS			0x805
++#define BCMA_CORE_ETHERNET		0x806
++#define BCMA_CORE_V90			0x807
++#define BCMA_CORE_USB11_HOSTDEV		0x808
++#define BCMA_CORE_ADSL			0x809
++#define BCMA_CORE_ILINE100		0x80A
++#define BCMA_CORE_IPSEC			0x80B
++#define BCMA_CORE_UTOPIA		0x80C
++#define BCMA_CORE_PCMCIA		0x80D
++#define BCMA_CORE_INTERNAL_MEM		0x80E
++#define BCMA_CORE_MEMC_SDRAM		0x80F
++#define BCMA_CORE_OFDM			0x810
++#define BCMA_CORE_EXTIF			0x811
++#define BCMA_CORE_80211			0x812
++#define BCMA_CORE_PHY_A			0x813
++#define BCMA_CORE_PHY_B			0x814
++#define BCMA_CORE_PHY_G			0x815
++#define BCMA_CORE_MIPS_3302		0x816
++#define BCMA_CORE_USB11_HOST		0x817
++#define BCMA_CORE_USB11_DEV		0x818
++#define BCMA_CORE_USB20_HOST		0x819
++#define BCMA_CORE_USB20_DEV		0x81A
++#define BCMA_CORE_SDIO_HOST		0x81B
++#define BCMA_CORE_ROBOSWITCH		0x81C
++#define BCMA_CORE_PARA_ATA		0x81D
++#define BCMA_CORE_SATA_XORDMA		0x81E
++#define BCMA_CORE_ETHERNET_GBIT		0x81F
++#define BCMA_CORE_PCIE			0x820
++#define BCMA_CORE_PHY_N			0x821
++#define BCMA_CORE_SRAM_CTL		0x822
++#define BCMA_CORE_MINI_MACPHY		0x823
++#define BCMA_CORE_ARM_1176		0x824
++#define BCMA_CORE_ARM_7TDMI		0x825
++#define BCMA_CORE_PHY_LP		0x826
++#define BCMA_CORE_PMU			0x827
++#define BCMA_CORE_PHY_SSN		0x828
++#define BCMA_CORE_SDIO_DEV		0x829
++#define BCMA_CORE_ARM_CM3		0x82A
++#define BCMA_CORE_PHY_HT		0x82B
++#define BCMA_CORE_MIPS_74K		0x82C
++#define BCMA_CORE_MAC_GBIT		0x82D
++#define BCMA_CORE_DDR12_MEM_CTL		0x82E
++#define BCMA_CORE_PCIE_RC		0x82F	/* PCIe Root Complex */
++#define BCMA_CORE_OCP_OCP_BRIDGE	0x830
++#define BCMA_CORE_SHARED_COMMON		0x831
++#define BCMA_CORE_OCP_AHB_BRIDGE	0x832
++#define BCMA_CORE_SPI_HOST		0x833
++#define BCMA_CORE_I2S			0x834
++#define BCMA_CORE_SDR_DDR1_MEM_CTL	0x835	/* SDR/DDR1 memory controller core */
++#define BCMA_CORE_SHIM			0x837	/* SHIM component in ubus/6362 */
++#define BCMA_CORE_DEFAULT		0xFFF
 +
-+void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
-+{
-+	struct bcma_bus *bus = pc->core->bus;
-+	struct bcma_drv_pci_host *pc_host;
-+	u32 tmp;
-+	u32 pci_membase_1G;
-+	unsigned long io_map_base;
++#define BCMA_MAX_NR_CORES		16
 +
-+	pr_info("PCIEcore in host mode found\n");
++struct bcma_device {
++	struct bcma_bus *bus;
++	struct bcma_device_id id;
 +
-+	pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL);
-+	if (!pc_host)  {
-+		pr_err("can not allocate memory");
-+		return;
-+	}
++	struct device dev;
++	struct device *dma_dev;
 +
-+	pc->host_controller = pc_host;
-+	pc_host->pci_controller.io_resource = &pc_host->io_resource;
-+	pc_host->pci_controller.mem_resource = &pc_host->mem_resource;
-+	pc_host->pci_controller.pci_ops = &pc_host->pci_ops;
-+	pc_host->pdev = pc;
++	unsigned int irq;
++	bool dev_registered;
 +
-+	pci_membase_1G = BCMA_SOC_PCI_DMA;
-+	pc_host->host_cfg_addr = BCMA_SOC_PCI_CFG;
++	u8 core_index;
++	u8 core_unit;
 +
-+	pc_host->pci_ops.read = bcma_core_pci_hostmode_read_config;
-+	pc_host->pci_ops.write = bcma_core_pci_hostmode_write_config;
++	u32 addr;
++	u32 wrap;
 +
-+	pc_host->mem_resource.name = "BCMA PCIcore external memory",
-+	pc_host->mem_resource.start = BCMA_SOC_PCI_DMA;
-+	pc_host->mem_resource.end = BCMA_SOC_PCI_DMA + BCMA_SOC_PCI_DMA_SZ - 1;
-+	pc_host->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;
++	void __iomem *io_addr;
++	void __iomem *io_wrap;
 +
-+	pc_host->io_resource.name = "BCMA PCIcore external I/O",
-+	pc_host->io_resource.start = 0x100;
-+	pc_host->io_resource.end = 0x7FF;
-+	pc_host->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED;
++	void *drvdata;
++	struct list_head list;
++};
 +
-+	/* Reset RC */
-+	udelay(3000);
-+	pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE);
-+	udelay(1000);
-+	pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST |
-+			BCMA_CORE_PCI_CTL_RST_OE);
++static inline void *bcma_get_drvdata(struct bcma_device *core)
++{
++	return core->drvdata;
++}
++static inline void bcma_set_drvdata(struct bcma_device *core, void *drvdata)
++{
++	core->drvdata = drvdata;
++}
 +
-+	/* 64 MB I/O access window. On 4716, use
-+	 * sbtopcie0 to access the device registers. We
-+	 * can't use address match 2 (1 GB window) region
-+	 * as mips can't generate 64-bit address on the
-+	 * backplane.
-+	 */
-+	if (bus->chipinfo.id == 0x4716 || bus->chipinfo.id == 0x4748) {
-+		pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
-+		pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
-+					    BCMA_SOC_PCI_MEM_SZ - 1;
-+		pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
-+				BCMA_CORE_PCI_SBTOPCI_MEM | BCMA_SOC_PCI_MEM);
-+	} else if (bus->chipinfo.id == 0x5300) {
-+		tmp = BCMA_CORE_PCI_SBTOPCI_MEM;
-+		tmp |= BCMA_CORE_PCI_SBTOPCI_PREF;
-+		tmp |= BCMA_CORE_PCI_SBTOPCI_BURST;
-+		if (pc->core->core_unit == 0) {
-+			pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
-+			pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
-+						    BCMA_SOC_PCI_MEM_SZ - 1;
-+			pci_membase_1G = BCMA_SOC_PCIE_DMA_H32;
-+			pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
-+					tmp | BCMA_SOC_PCI_MEM);
-+		} else if (pc->core->core_unit == 1) {
-+			pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM;
-+			pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM +
-+						    BCMA_SOC_PCI_MEM_SZ - 1;
-+			pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32;
-+			pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG;
-+			pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
-+					tmp | BCMA_SOC_PCI1_MEM);
-+		}
-+	} else
-+		pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
-+				BCMA_CORE_PCI_SBTOPCI_IO);
++struct bcma_driver {
++	const char *name;
++	const struct bcma_device_id *id_table;
 +
-+	/* 64 MB configuration access window */
-+	pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0);
++	int (*probe)(struct bcma_device *dev);
++	void (*remove)(struct bcma_device *dev);
++	int (*suspend)(struct bcma_device *dev);
++	int (*resume)(struct bcma_device *dev);
++	void (*shutdown)(struct bcma_device *dev);
 +
-+	/* 1 GB memory access window */
-+	pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI2,
-+			BCMA_CORE_PCI_SBTOPCI_MEM | pci_membase_1G);
++	struct device_driver drv;
++};
++extern
++int __bcma_driver_register(struct bcma_driver *drv, struct module *owner);
++#define bcma_driver_register(drv) \
++	__bcma_driver_register(drv, THIS_MODULE)
 +
++extern void bcma_driver_unregister(struct bcma_driver *drv);
 +
-+	/* As per PCI Express Base Spec 1.1 we need to wait for
-+	 * at least 100 ms from the end of a reset (cold/warm/hot)
-+	 * before issuing configuration requests to PCI Express
-+	 * devices.
-+	 */
-+	udelay(100000);
++/* Set a fallback SPROM.
++ * See kdoc at the function definition for complete documentation. */
++extern int bcma_arch_register_fallback_sprom(
++		int (*sprom_callback)(struct bcma_bus *bus,
++		struct ssb_sprom *out));
 +
-+	bcma_core_pci_enable_crs(pc);
++struct bcma_bus {
++	/* The MMIO area. */
++	void __iomem *mmio;
 +
-+	/* Enable PCI bridge BAR0 memory & master access */
-+	tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
-+	bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp));
++	const struct bcma_host_ops *ops;
 +
-+	/* Enable PCI interrupts */
-+	pcicore_write32(pc, BCMA_CORE_PCI_IMASK, BCMA_CORE_PCI_IMASK_INTA);
++	enum bcma_hosttype hosttype;
++	union {
++		/* Pointer to the PCI bus (only for BCMA_HOSTTYPE_PCI) */
++		struct pci_dev *host_pci;
++		/* Pointer to the SDIO device (only for BCMA_HOSTTYPE_SDIO) */
++		struct sdio_func *host_sdio;
++	};
 +
-+	/* Ok, ready to run, register it to the system.
-+	 * The following needs change, if we want to port hostmode
-+	 * to non-MIPS platform. */
-+	io_map_base = (unsigned long)ioremap_nocache(BCMA_SOC_PCI_MEM,
-+						     0x04000000);
-+	pc_host->pci_controller.io_map_base = io_map_base;
-+	set_io_port_base(pc_host->pci_controller.io_map_base);
-+	/* Give some time to the PCI controller to configure itself with the new
-+	 * values. Not waiting at this point causes crashes of the machine. */
-+	mdelay(10);
-+	register_pci_controller(&pc_host->pci_controller);
-+	return;
-+}
++	struct bcma_chipinfo chipinfo;
 +
-+/* Early PCI fixup for a device on the PCI-core bridge. */
-+static void bcma_core_pci_fixup_pcibridge(struct pci_dev *dev)
-+{
-+	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
-+		/* This is not a device on the PCI-core bridge. */
-+		return;
-+	}
-+	if (PCI_SLOT(dev->devfn) != 0)
-+		return;
++	struct bcma_boardinfo boardinfo;
 +
-+	pr_info("PCI: Fixing up bridge %s\n", pci_name(dev));
++	struct bcma_device *mapped_core;
++	struct list_head cores;
++	u8 nr_cores;
++	u8 init_done:1;
++	u8 num;
 +
-+	/* Enable PCI bridge bus mastering and memory space */
-+	pci_set_master(dev);
-+	if (pcibios_enable_device(dev, ~0) < 0) {
-+		pr_err("PCI: BCMA bridge enable failed\n");
-+		return;
-+	}
++	struct bcma_drv_cc drv_cc;
++	struct bcma_drv_pci drv_pci;
++	struct bcma_drv_mips drv_mips;
 +
-+	/* Enable PCI bridge BAR1 prefetch and burst */
-+	pci_write_config_dword(dev, BCMA_PCI_BAR1_CONTROL, 3);
++	/* We decided to share SPROM struct with SSB as long as we do not need
++	 * any hacks for BCMA. This simplifies drivers code. */
++	struct ssb_sprom sprom;
++};
++
++static inline u32 bcma_read8(struct bcma_device *core, u16 offset)
++{
++	return core->bus->ops->read8(core, offset);
++}
++static inline u32 bcma_read16(struct bcma_device *core, u16 offset)
++{
++	return core->bus->ops->read16(core, offset);
++}
++static inline u32 bcma_read32(struct bcma_device *core, u16 offset)
++{
++	return core->bus->ops->read32(core, offset);
++}
++static inline
++void bcma_write8(struct bcma_device *core, u16 offset, u32 value)
++{
++	core->bus->ops->write8(core, offset, value);
++}
++static inline
++void bcma_write16(struct bcma_device *core, u16 offset, u32 value)
++{
++	core->bus->ops->write16(core, offset, value);
++}
++static inline
++void bcma_write32(struct bcma_device *core, u16 offset, u32 value)
++{
++	core->bus->ops->write32(core, offset, value);
++}
++#ifdef CONFIG_BCMA_BLOCKIO
++static inline void bcma_block_read(struct bcma_device *core, void *buffer,
++				   size_t count, u16 offset, u8 reg_width)
++{
++	core->bus->ops->block_read(core, buffer, count, offset, reg_width);
++}
++static inline void bcma_block_write(struct bcma_device *core,
++				    const void *buffer, size_t count,
++				    u16 offset, u8 reg_width)
++{
++	core->bus->ops->block_write(core, buffer, count, offset, reg_width);
++}
++#endif
++static inline u32 bcma_aread32(struct bcma_device *core, u16 offset)
++{
++	return core->bus->ops->aread32(core, offset);
++}
++static inline
++void bcma_awrite32(struct bcma_device *core, u16 offset, u32 value)
++{
++	core->bus->ops->awrite32(core, offset, value);
++}
++
++static inline void bcma_mask32(struct bcma_device *cc, u16 offset, u32 mask)
++{
++	bcma_write32(cc, offset, bcma_read32(cc, offset) & mask);
++}
++static inline void bcma_set32(struct bcma_device *cc, u16 offset, u32 set)
++{
++	bcma_write32(cc, offset, bcma_read32(cc, offset) | set);
++}
++static inline void bcma_maskset32(struct bcma_device *cc,
++				  u16 offset, u32 mask, u32 set)
++{
++	bcma_write32(cc, offset, (bcma_read32(cc, offset) & mask) | set);
++}
++static inline void bcma_mask16(struct bcma_device *cc, u16 offset, u16 mask)
++{
++	bcma_write16(cc, offset, bcma_read16(cc, offset) & mask);
 +}
-+DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_pcibridge);
-+
-+/* Early PCI fixup for all PCI-cores to set the correct memory address. */
-+static void bcma_core_pci_fixup_addresses(struct pci_dev *dev)
++static inline void bcma_set16(struct bcma_device *cc, u16 offset, u16 set)
 +{
-+	struct resource *res;
-+	int pos;
++	bcma_write16(cc, offset, bcma_read16(cc, offset) | set);
++}
++static inline void bcma_maskset16(struct bcma_device *cc,
++				  u16 offset, u16 mask, u16 set)
++{
++	bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set);
++}
 +
-+	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
-+		/* This is not a device on the PCI-core bridge. */
-+		return;
-+	}
-+	if (PCI_SLOT(dev->devfn) == 0)
-+		return;
++extern struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid);
++extern bool bcma_core_is_enabled(struct bcma_device *core);
++extern void bcma_core_disable(struct bcma_device *core, u32 flags);
++extern int bcma_core_enable(struct bcma_device *core, u32 flags);
++extern void bcma_core_set_clockmode(struct bcma_device *core,
++				    enum bcma_clkmode clkmode);
++extern void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status,
++			      bool on);
++#define BCMA_DMA_TRANSLATION_MASK	0xC0000000
++#define  BCMA_DMA_TRANSLATION_NONE	0x00000000
++#define  BCMA_DMA_TRANSLATION_DMA32_CMT	0x40000000 /* Client Mode Translation for 32-bit DMA */
++#define  BCMA_DMA_TRANSLATION_DMA64_CMT	0x80000000 /* Client Mode Translation for 64-bit DMA */
++extern u32 bcma_core_dma_translation(struct bcma_device *core);
 +
-+	pr_info("PCI: Fixing up addresses %s\n", pci_name(dev));
++#endif /* LINUX_BCMA_H_ */
+--- /dev/null
++++ b/include/linux/bcma/bcma_driver_chipcommon.h
+@@ -0,0 +1,415 @@
++#ifndef LINUX_BCMA_DRIVER_CC_H_
++#define LINUX_BCMA_DRIVER_CC_H_
 +
-+	for (pos = 0; pos < 6; pos++) {
-+		res = &dev->resource[pos];
-+		if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM))
-+			pci_assign_resource(dev, pos);
-+	}
-+}
-+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses);
++/** ChipCommon core registers. **/
++#define BCMA_CC_ID			0x0000
++#define  BCMA_CC_ID_ID			0x0000FFFF
++#define  BCMA_CC_ID_ID_SHIFT		0
++#define  BCMA_CC_ID_REV			0x000F0000
++#define  BCMA_CC_ID_REV_SHIFT		16
++#define  BCMA_CC_ID_PKG			0x00F00000
++#define  BCMA_CC_ID_PKG_SHIFT		20
++#define  BCMA_CC_ID_NRCORES		0x0F000000
++#define  BCMA_CC_ID_NRCORES_SHIFT	24
++#define  BCMA_CC_ID_TYPE		0xF0000000
++#define  BCMA_CC_ID_TYPE_SHIFT		28
++#define BCMA_CC_CAP			0x0004		/* Capabilities */
++#define  BCMA_CC_CAP_NRUART		0x00000003	/* # of UARTs */
++#define  BCMA_CC_CAP_MIPSEB		0x00000004	/* MIPS in BigEndian Mode */
++#define  BCMA_CC_CAP_UARTCLK		0x00000018	/* UART clock select */
++#define   BCMA_CC_CAP_UARTCLK_INT	0x00000008	/* UARTs are driven by internal divided clock */
++#define  BCMA_CC_CAP_UARTGPIO		0x00000020	/* UARTs on GPIO 15-12 */
++#define  BCMA_CC_CAP_EXTBUS		0x000000C0	/* External buses present */
++#define  BCMA_CC_CAP_FLASHT		0x00000700	/* Flash Type */
++#define   BCMA_CC_FLASHT_NONE		0x00000000	/* No flash */
++#define   BCMA_CC_FLASHT_STSER		0x00000100	/* ST serial flash */
++#define   BCMA_CC_FLASHT_ATSER		0x00000200	/* Atmel serial flash */
++#define   BCMA_CC_FLASHT_NFLASH		0x00000200
++#define	  BCMA_CC_FLASHT_PARA		0x00000700	/* Parallel flash */
++#define  BCMA_CC_CAP_PLLT		0x00038000	/* PLL Type */
++#define   BCMA_PLLTYPE_NONE		0x00000000
++#define   BCMA_PLLTYPE_1		0x00010000	/* 48Mhz base, 3 dividers */
++#define   BCMA_PLLTYPE_2		0x00020000	/* 48Mhz, 4 dividers */
++#define   BCMA_PLLTYPE_3		0x00030000	/* 25Mhz, 2 dividers */
++#define   BCMA_PLLTYPE_4		0x00008000	/* 48Mhz, 4 dividers */
++#define   BCMA_PLLTYPE_5		0x00018000	/* 25Mhz, 4 dividers */
++#define   BCMA_PLLTYPE_6		0x00028000	/* 100/200 or 120/240 only */
++#define   BCMA_PLLTYPE_7		0x00038000	/* 25Mhz, 4 dividers */
++#define  BCMA_CC_CAP_PCTL		0x00040000	/* Power Control */
++#define  BCMA_CC_CAP_OTPS		0x00380000	/* OTP size */
++#define  BCMA_CC_CAP_OTPS_SHIFT		19
++#define  BCMA_CC_CAP_OTPS_BASE		5
++#define  BCMA_CC_CAP_JTAGM		0x00400000	/* JTAG master present */
++#define  BCMA_CC_CAP_BROM		0x00800000	/* Internal boot ROM active */
++#define  BCMA_CC_CAP_64BIT		0x08000000	/* 64-bit Backplane */
++#define  BCMA_CC_CAP_PMU		0x10000000	/* PMU available (rev >= 20) */
++#define  BCMA_CC_CAP_ECI		0x20000000	/* ECI available (rev >= 20) */
++#define  BCMA_CC_CAP_SPROM		0x40000000	/* SPROM present */
++#define BCMA_CC_CORECTL			0x0008
++#define  BCMA_CC_CORECTL_UARTCLK0	0x00000001	/* Drive UART with internal clock */
++#define	 BCMA_CC_CORECTL_SE		0x00000002	/* sync clk out enable (corerev >= 3) */
++#define  BCMA_CC_CORECTL_UARTCLKEN	0x00000008	/* UART clock enable (rev >= 21) */
++#define BCMA_CC_BIST			0x000C
++#define BCMA_CC_OTPS			0x0010		/* OTP status */
++#define	 BCMA_CC_OTPS_PROGFAIL		0x80000000
++#define	 BCMA_CC_OTPS_PROTECT		0x00000007
++#define	 BCMA_CC_OTPS_HW_PROTECT	0x00000001
++#define	 BCMA_CC_OTPS_SW_PROTECT	0x00000002
++#define	 BCMA_CC_OTPS_CID_PROTECT	0x00000004
++#define  BCMA_CC_OTPS_GU_PROG_IND	0x00000F00	/* General Use programmed indication */
++#define  BCMA_CC_OTPS_GU_PROG_IND_SHIFT	8
++#define  BCMA_CC_OTPS_GU_PROG_HW	0x00000100	/* HW region programmed */
++#define BCMA_CC_OTPC			0x0014		/* OTP control */
++#define	 BCMA_CC_OTPC_RECWAIT		0xFF000000
++#define	 BCMA_CC_OTPC_PROGWAIT		0x00FFFF00
++#define	 BCMA_CC_OTPC_PRW_SHIFT		8
++#define	 BCMA_CC_OTPC_MAXFAIL		0x00000038
++#define	 BCMA_CC_OTPC_VSEL		0x00000006
++#define	 BCMA_CC_OTPC_SELVL		0x00000001
++#define BCMA_CC_OTPP			0x0018		/* OTP prog */
++#define	 BCMA_CC_OTPP_COL		0x000000FF
++#define	 BCMA_CC_OTPP_ROW		0x0000FF00
++#define	 BCMA_CC_OTPP_ROW_SHIFT		8
++#define	 BCMA_CC_OTPP_READERR		0x10000000
++#define	 BCMA_CC_OTPP_VALUE		0x20000000
++#define	 BCMA_CC_OTPP_READ		0x40000000
++#define	 BCMA_CC_OTPP_START		0x80000000
++#define	 BCMA_CC_OTPP_BUSY		0x80000000
++#define BCMA_CC_OTPL			0x001C		/* OTP layout */
++#define  BCMA_CC_OTPL_GURGN_OFFSET	0x00000FFF	/* offset of general use region */
++#define BCMA_CC_IRQSTAT			0x0020
++#define BCMA_CC_IRQMASK			0x0024
++#define	 BCMA_CC_IRQ_GPIO		0x00000001	/* gpio intr */
++#define	 BCMA_CC_IRQ_EXT		0x00000002	/* ro: ext intr pin (corerev >= 3) */
++#define	 BCMA_CC_IRQ_WDRESET		0x80000000	/* watchdog reset occurred */
++#define BCMA_CC_CHIPCTL			0x0028		/* Rev >= 11 only */
++#define BCMA_CC_CHIPSTAT		0x002C		/* Rev >= 11 only */
++#define  BCMA_CC_CHIPST_4313_SPROM_PRESENT	1
++#define  BCMA_CC_CHIPST_4313_OTP_PRESENT	2
++#define  BCMA_CC_CHIPST_4331_SPROM_PRESENT	2
++#define  BCMA_CC_CHIPST_4331_OTP_PRESENT	4
++#define BCMA_CC_JCMD			0x0030		/* Rev >= 10 only */
++#define  BCMA_CC_JCMD_START		0x80000000
++#define  BCMA_CC_JCMD_BUSY		0x80000000
++#define  BCMA_CC_JCMD_PAUSE		0x40000000
++#define  BCMA_CC_JCMD0_ACC_MASK		0x0000F000
++#define  BCMA_CC_JCMD0_ACC_IRDR		0x00000000
++#define  BCMA_CC_JCMD0_ACC_DR		0x00001000
++#define  BCMA_CC_JCMD0_ACC_IR		0x00002000
++#define  BCMA_CC_JCMD0_ACC_RESET	0x00003000
++#define  BCMA_CC_JCMD0_ACC_IRPDR	0x00004000
++#define  BCMA_CC_JCMD0_ACC_PDR		0x00005000
++#define  BCMA_CC_JCMD0_IRW_MASK		0x00000F00
++#define  BCMA_CC_JCMD_ACC_MASK		0x000F0000	/* Changes for corerev 11 */
++#define  BCMA_CC_JCMD_ACC_IRDR		0x00000000
++#define  BCMA_CC_JCMD_ACC_DR		0x00010000
++#define  BCMA_CC_JCMD_ACC_IR		0x00020000
++#define  BCMA_CC_JCMD_ACC_RESET		0x00030000
++#define  BCMA_CC_JCMD_ACC_IRPDR		0x00040000
++#define  BCMA_CC_JCMD_ACC_PDR		0x00050000
++#define  BCMA_CC_JCMD_IRW_MASK		0x00001F00
++#define  BCMA_CC_JCMD_IRW_SHIFT		8
++#define  BCMA_CC_JCMD_DRW_MASK		0x0000003F
++#define BCMA_CC_JIR			0x0034		/* Rev >= 10 only */
++#define BCMA_CC_JDR			0x0038		/* Rev >= 10 only */
++#define BCMA_CC_JCTL			0x003C		/* Rev >= 10 only */
++#define  BCMA_CC_JCTL_FORCE_CLK		4		/* Force clock */
++#define  BCMA_CC_JCTL_EXT_EN		2		/* Enable external targets */
++#define  BCMA_CC_JCTL_EN		1		/* Enable Jtag master */
++#define BCMA_CC_FLASHCTL		0x0040
++#define  BCMA_CC_FLASHCTL_START		0x80000000
++#define  BCMA_CC_FLASHCTL_BUSY		BCMA_CC_FLASHCTL_START
++#define BCMA_CC_FLASHADDR		0x0044
++#define BCMA_CC_FLASHDATA		0x0048
++#define BCMA_CC_BCAST_ADDR		0x0050
++#define BCMA_CC_BCAST_DATA		0x0054
++#define BCMA_CC_GPIOPULLUP		0x0058		/* Rev >= 20 only */
++#define BCMA_CC_GPIOPULLDOWN		0x005C		/* Rev >= 20 only */
++#define BCMA_CC_GPIOIN			0x0060
++#define BCMA_CC_GPIOOUT			0x0064
++#define BCMA_CC_GPIOOUTEN		0x0068
++#define BCMA_CC_GPIOCTL			0x006C
++#define BCMA_CC_GPIOPOL			0x0070
++#define BCMA_CC_GPIOIRQ			0x0074
++#define BCMA_CC_WATCHDOG		0x0080
++#define BCMA_CC_GPIOTIMER		0x0088		/* LED powersave (corerev >= 16) */
++#define  BCMA_CC_GPIOTIMER_OFFTIME	0x0000FFFF
++#define  BCMA_CC_GPIOTIMER_OFFTIME_SHIFT	0
++#define  BCMA_CC_GPIOTIMER_ONTIME	0xFFFF0000
++#define  BCMA_CC_GPIOTIMER_ONTIME_SHIFT	16
++#define BCMA_CC_GPIOTOUTM		0x008C		/* LED powersave (corerev >= 16) */
++#define BCMA_CC_CLOCK_N			0x0090
++#define BCMA_CC_CLOCK_SB		0x0094
++#define BCMA_CC_CLOCK_PCI		0x0098
++#define BCMA_CC_CLOCK_M2		0x009C
++#define BCMA_CC_CLOCK_MIPS		0x00A0
++#define BCMA_CC_CLKDIV			0x00A4		/* Rev >= 3 only */
++#define	 BCMA_CC_CLKDIV_SFLASH		0x0F000000
++#define	 BCMA_CC_CLKDIV_SFLASH_SHIFT	24
++#define	 BCMA_CC_CLKDIV_OTP		0x000F0000
++#define	 BCMA_CC_CLKDIV_OTP_SHIFT	16
++#define	 BCMA_CC_CLKDIV_JTAG		0x00000F00
++#define	 BCMA_CC_CLKDIV_JTAG_SHIFT	8
++#define	 BCMA_CC_CLKDIV_UART		0x000000FF
++#define BCMA_CC_CAP_EXT			0x00AC		/* Capabilities */
++#define BCMA_CC_PLLONDELAY		0x00B0		/* Rev >= 4 only */
++#define BCMA_CC_FREFSELDELAY		0x00B4		/* Rev >= 4 only */
++#define BCMA_CC_SLOWCLKCTL		0x00B8		/* 6 <= Rev <= 9 only */
++#define  BCMA_CC_SLOWCLKCTL_SRC		0x00000007	/* slow clock source mask */
++#define	  BCMA_CC_SLOWCLKCTL_SRC_LPO	0x00000000	/* source of slow clock is LPO */
++#define   BCMA_CC_SLOWCLKCTL_SRC_XTAL	0x00000001	/* source of slow clock is crystal */
++#define	  BCMA_CC_SLOECLKCTL_SRC_PCI	0x00000002	/* source of slow clock is PCI */
++#define  BCMA_CC_SLOWCLKCTL_LPOFREQ	0x00000200	/* LPOFreqSel, 1: 160Khz, 0: 32KHz */
++#define  BCMA_CC_SLOWCLKCTL_LPOPD	0x00000400	/* LPOPowerDown, 1: LPO is disabled, 0: LPO is enabled */
++#define  BCMA_CC_SLOWCLKCTL_FSLOW	0x00000800	/* ForceSlowClk, 1: sb/cores running on slow clock, 0: power logic control */
++#define  BCMA_CC_SLOWCLKCTL_IPLL	0x00001000	/* IgnorePllOffReq, 1/0: power logic ignores/honors PLL clock disable requests from core */
++#define  BCMA_CC_SLOWCLKCTL_ENXTAL	0x00002000	/* XtalControlEn, 1/0: power logic does/doesn't disable crystal when appropriate */
++#define  BCMA_CC_SLOWCLKCTL_XTALPU	0x00004000	/* XtalPU (RO), 1/0: crystal running/disabled */
++#define  BCMA_CC_SLOWCLKCTL_CLKDIV	0xFFFF0000	/* ClockDivider (SlowClk = 1/(4+divisor)) */
++#define  BCMA_CC_SLOWCLKCTL_CLKDIV_SHIFT	16
++#define BCMA_CC_SYSCLKCTL		0x00C0		/* Rev >= 3 only */
++#define	 BCMA_CC_SYSCLKCTL_IDLPEN	0x00000001	/* ILPen: Enable Idle Low Power */
++#define	 BCMA_CC_SYSCLKCTL_ALPEN	0x00000002	/* ALPen: Enable Active Low Power */
++#define	 BCMA_CC_SYSCLKCTL_PLLEN	0x00000004	/* ForcePLLOn */
++#define	 BCMA_CC_SYSCLKCTL_FORCEALP	0x00000008	/* Force ALP (or HT if ALPen is not set */
++#define	 BCMA_CC_SYSCLKCTL_FORCEHT	0x00000010	/* Force HT */
++#define  BCMA_CC_SYSCLKCTL_CLKDIV	0xFFFF0000	/* ClkDiv  (ILP = 1/(4+divisor)) */
++#define  BCMA_CC_SYSCLKCTL_CLKDIV_SHIFT	16
++#define BCMA_CC_CLKSTSTR		0x00C4		/* Rev >= 3 only */
++#define BCMA_CC_EROM			0x00FC
++#define BCMA_CC_PCMCIA_CFG		0x0100
++#define BCMA_CC_PCMCIA_MEMWAIT		0x0104
++#define BCMA_CC_PCMCIA_ATTRWAIT		0x0108
++#define BCMA_CC_PCMCIA_IOWAIT		0x010C
++#define BCMA_CC_IDE_CFG			0x0110
++#define BCMA_CC_IDE_MEMWAIT		0x0114
++#define BCMA_CC_IDE_ATTRWAIT		0x0118
++#define BCMA_CC_IDE_IOWAIT		0x011C
++#define BCMA_CC_PROG_CFG		0x0120
++#define BCMA_CC_PROG_WAITCNT		0x0124
++#define BCMA_CC_FLASH_CFG		0x0128
++#define  BCMA_CC_FLASH_CFG_DS		0x0010	/* Data size, 0=8bit, 1=16bit */
++#define BCMA_CC_FLASH_WAITCNT		0x012C
++#define BCMA_CC_SROM_CONTROL		0x0190
++#define  BCMA_CC_SROM_CONTROL_START	0x80000000
++#define  BCMA_CC_SROM_CONTROL_BUSY	0x80000000
++#define  BCMA_CC_SROM_CONTROL_OPCODE	0x60000000
++#define  BCMA_CC_SROM_CONTROL_OP_READ	0x00000000
++#define  BCMA_CC_SROM_CONTROL_OP_WRITE	0x20000000
++#define  BCMA_CC_SROM_CONTROL_OP_WRDIS	0x40000000
++#define  BCMA_CC_SROM_CONTROL_OP_WREN	0x60000000
++#define  BCMA_CC_SROM_CONTROL_OTPSEL	0x00000010
++#define  BCMA_CC_SROM_CONTROL_LOCK	0x00000008
++#define  BCMA_CC_SROM_CONTROL_SIZE_MASK	0x00000006
++#define  BCMA_CC_SROM_CONTROL_SIZE_1K	0x00000000
++#define  BCMA_CC_SROM_CONTROL_SIZE_4K	0x00000002
++#define  BCMA_CC_SROM_CONTROL_SIZE_16K	0x00000004
++#define  BCMA_CC_SROM_CONTROL_SIZE_SHIFT	1
++#define  BCMA_CC_SROM_CONTROL_PRESENT	0x00000001
++/* 0x1E0 is defined as shared BCMA_CLKCTLST */
++#define BCMA_CC_HW_WORKAROUND		0x01E4 /* Hardware workaround (rev >= 20) */
++#define BCMA_CC_UART0_DATA		0x0300
++#define BCMA_CC_UART0_IMR		0x0304
++#define BCMA_CC_UART0_FCR		0x0308
++#define BCMA_CC_UART0_LCR		0x030C
++#define BCMA_CC_UART0_MCR		0x0310
++#define BCMA_CC_UART0_LSR		0x0314
++#define BCMA_CC_UART0_MSR		0x0318
++#define BCMA_CC_UART0_SCRATCH		0x031C
++#define BCMA_CC_UART1_DATA		0x0400
++#define BCMA_CC_UART1_IMR		0x0404
++#define BCMA_CC_UART1_FCR		0x0408
++#define BCMA_CC_UART1_LCR		0x040C
++#define BCMA_CC_UART1_MCR		0x0410
++#define BCMA_CC_UART1_LSR		0x0414
++#define BCMA_CC_UART1_MSR		0x0418
++#define BCMA_CC_UART1_SCRATCH		0x041C
++/* PMU registers (rev >= 20) */
++#define BCMA_CC_PMU_CTL			0x0600 /* PMU control */
++#define  BCMA_CC_PMU_CTL_ILP_DIV	0xFFFF0000 /* ILP div mask */
++#define  BCMA_CC_PMU_CTL_ILP_DIV_SHIFT	16
++#define  BCMA_CC_PMU_CTL_PLL_UPD	0x00000400
++#define  BCMA_CC_PMU_CTL_NOILPONW	0x00000200 /* No ILP on wait */
++#define  BCMA_CC_PMU_CTL_HTREQEN	0x00000100 /* HT req enable */
++#define  BCMA_CC_PMU_CTL_ALPREQEN	0x00000080 /* ALP req enable */
++#define  BCMA_CC_PMU_CTL_XTALFREQ	0x0000007C /* Crystal freq */
++#define  BCMA_CC_PMU_CTL_XTALFREQ_SHIFT	2
++#define  BCMA_CC_PMU_CTL_ILPDIVEN	0x00000002 /* ILP div enable */
++#define  BCMA_CC_PMU_CTL_LPOSEL		0x00000001 /* LPO sel */
++#define BCMA_CC_PMU_CAP			0x0604 /* PMU capabilities */
++#define  BCMA_CC_PMU_CAP_REVISION	0x000000FF /* Revision mask */
++#define BCMA_CC_PMU_STAT		0x0608 /* PMU status */
++#define  BCMA_CC_PMU_STAT_INTPEND	0x00000040 /* Interrupt pending */
++#define  BCMA_CC_PMU_STAT_SBCLKST	0x00000030 /* Backplane clock status? */
++#define  BCMA_CC_PMU_STAT_HAVEALP	0x00000008 /* ALP available */
++#define  BCMA_CC_PMU_STAT_HAVEHT	0x00000004 /* HT available */
++#define  BCMA_CC_PMU_STAT_RESINIT	0x00000003 /* Res init */
++#define BCMA_CC_PMU_RES_STAT		0x060C /* PMU res status */
++#define BCMA_CC_PMU_RES_PEND		0x0610 /* PMU res pending */
++#define BCMA_CC_PMU_TIMER		0x0614 /* PMU timer */
++#define BCMA_CC_PMU_MINRES_MSK		0x0618 /* PMU min res mask */
++#define BCMA_CC_PMU_MAXRES_MSK		0x061C /* PMU max res mask */
++#define BCMA_CC_PMU_RES_TABSEL		0x0620 /* PMU res table sel */
++#define BCMA_CC_PMU_RES_DEPMSK		0x0624 /* PMU res dep mask */
++#define BCMA_CC_PMU_RES_UPDNTM		0x0628 /* PMU res updown timer */
++#define BCMA_CC_PMU_RES_TIMER		0x062C /* PMU res timer */
++#define BCMA_CC_PMU_CLKSTRETCH		0x0630 /* PMU clockstretch */
++#define BCMA_CC_PMU_WATCHDOG		0x0634 /* PMU watchdog */
++#define BCMA_CC_PMU_RES_REQTS		0x0640 /* PMU res req timer sel */
++#define BCMA_CC_PMU_RES_REQT		0x0644 /* PMU res req timer */
++#define BCMA_CC_PMU_RES_REQM		0x0648 /* PMU res req mask */
++#define BCMA_CC_CHIPCTL_ADDR		0x0650
++#define BCMA_CC_CHIPCTL_DATA		0x0654
++#define BCMA_CC_REGCTL_ADDR		0x0658
++#define BCMA_CC_REGCTL_DATA		0x065C
++#define BCMA_CC_PLLCTL_ADDR		0x0660
++#define BCMA_CC_PLLCTL_DATA		0x0664
++#define BCMA_CC_SPROM			0x0800 /* SPROM beginning */
 +
-+/* This function is called when doing a pci_enable_device().
-+ * We must first check if the device is a device on the PCI-core bridge. */
-+int bcma_core_pci_plat_dev_init(struct pci_dev *dev)
-+{
-+	struct bcma_drv_pci_host *pc_host;
++/* Divider allocation in 4716/47162/5356 */
++#define BCMA_CC_PMU5_MAINPLL_CPU	1
++#define BCMA_CC_PMU5_MAINPLL_MEM	2
++#define BCMA_CC_PMU5_MAINPLL_SSB	3
 +
-+	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
-+		/* This is not a device on the PCI-core bridge. */
-+		return -ENODEV;
-+	}
-+	pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
-+			       pci_ops);
++/* PLL usage in 4716/47162 */
++#define BCMA_CC_PMU4716_MAINPLL_PLL0	12
 +
-+	pr_info("PCI: Fixing up device %s\n", pci_name(dev));
++/* PLL usage in 5356/5357 */
++#define BCMA_CC_PMU5356_MAINPLL_PLL0	0
++#define BCMA_CC_PMU5357_MAINPLL_PLL0	0
 +
-+	/* Fix up interrupt lines */
-+	dev->irq = bcma_core_mips_irq(pc_host->pdev->core) + 2;
-+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
++/* 4706 PMU */
++#define BCMA_CC_PMU4706_MAINPLL_PLL0	0
 +
-+	return 0;
-+}
-+EXPORT_SYMBOL(bcma_core_pci_plat_dev_init);
++/* ALP clock on pre-PMU chips */
++#define BCMA_CC_PMU_ALP_CLOCK		20000000
++/* HT clock for systems with PMU-enabled chipcommon */
++#define BCMA_CC_PMU_HT_CLOCK		80000000
 +
-+/* PCI device IRQ mapping. */
-+int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev)
-+{
-+	struct bcma_drv_pci_host *pc_host;
++/* PMU rev 5 (& 6) */
++#define BCMA_CC_PPL_P1P2_OFF		0
++#define BCMA_CC_PPL_P1_MASK		0x0f000000
++#define BCMA_CC_PPL_P1_SHIFT		24
++#define BCMA_CC_PPL_P2_MASK		0x00f00000
++#define BCMA_CC_PPL_P2_SHIFT		20
++#define BCMA_CC_PPL_M14_OFF		1
++#define BCMA_CC_PPL_MDIV_MASK		0x000000ff
++#define BCMA_CC_PPL_MDIV_WIDTH		8
++#define BCMA_CC_PPL_NM5_OFF		2
++#define BCMA_CC_PPL_NDIV_MASK		0xfff00000
++#define BCMA_CC_PPL_NDIV_SHIFT		20
++#define BCMA_CC_PPL_FMAB_OFF		3
++#define BCMA_CC_PPL_MRAT_MASK		0xf0000000
++#define BCMA_CC_PPL_MRAT_SHIFT		28
++#define BCMA_CC_PPL_ABRAT_MASK		0x08000000
++#define BCMA_CC_PPL_ABRAT_SHIFT		27
++#define BCMA_CC_PPL_FDIV_MASK		0x07ffffff
++#define BCMA_CC_PPL_PLLCTL_OFF		4
++#define BCMA_CC_PPL_PCHI_OFF		5
++#define BCMA_CC_PPL_PCHI_MASK		0x0000003f
 +
-+	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
-+		/* This is not a device on the PCI-core bridge. */
-+		return -ENODEV;
-+	}
++/* BCM4331 ChipControl numbers. */
++#define BCMA_CHIPCTL_4331_BT_COEXIST		BIT(0)	/* 0 disable */
++#define BCMA_CHIPCTL_4331_SECI			BIT(1)	/* 0 SECI is disabled (JATG functional) */
++#define BCMA_CHIPCTL_4331_EXT_LNA		BIT(2)	/* 0 disable */
++#define BCMA_CHIPCTL_4331_SPROM_GPIO13_15	BIT(3)	/* sprom/gpio13-15 mux */
++#define BCMA_CHIPCTL_4331_EXTPA_EN		BIT(4)	/* 0 ext pa disable, 1 ext pa enabled */
++#define BCMA_CHIPCTL_4331_GPIOCLK_ON_SPROMCS	BIT(5)	/* set drive out GPIO_CLK on sprom_cs pin */
++#define BCMA_CHIPCTL_4331_PCIE_MDIO_ON_SPROMCS	BIT(6)	/* use sprom_cs pin as PCIE mdio interface */
++#define BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5	BIT(7)	/* aband extpa will be at gpio2/5 and sprom_dout */
++#define BCMA_CHIPCTL_4331_OVR_PIPEAUXCLKEN	BIT(8)	/* override core control on pipe_AuxClkEnable */
++#define BCMA_CHIPCTL_4331_OVR_PIPEAUXPWRDOWN	BIT(9)	/* override core control on pipe_AuxPowerDown */
++#define BCMA_CHIPCTL_4331_PCIE_AUXCLKEN		BIT(10)	/* pcie_auxclkenable */
++#define BCMA_CHIPCTL_4331_PCIE_PIPE_PLLDOWN	BIT(11)	/* pcie_pipe_pllpowerdown */
++#define BCMA_CHIPCTL_4331_BT_SHD0_ON_GPIO4	BIT(16)	/* enable bt_shd0 at gpio4 */
++#define BCMA_CHIPCTL_4331_BT_SHD1_ON_GPIO5	BIT(17)	/* enable bt_shd1 at gpio5 */
 +
-+	pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
-+			       pci_ops);
-+	return bcma_core_mips_irq(pc_host->pdev->core) + 2;
-+}
-+EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq);
---- /dev/null
-+++ b/drivers/bcma/driver_mips.c
-@@ -0,0 +1,256 @@
-+/*
-+ * Broadcom specific AMBA
-+ * Broadcom MIPS32 74K core driver
-+ *
-+ * Copyright 2009, Broadcom Corporation
-+ * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
-+ * Copyright 2010, Bernhard Loos <bernhardloos@googlemail.com>
-+ * Copyright 2011, Hauke Mehrtens <hauke@hauke-m.de>
-+ *
-+ * Licensed under the GNU/GPL. See COPYING for details.
++/* Data for the PMU, if available.
++ * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
 + */
-+
-+#include "bcma_private.h"
-+
-+#include <linux/bcma/bcma.h>
-+
-+#include <linux/serial.h>
-+#include <linux/serial_core.h>
-+#include <linux/serial_reg.h>
-+#include <linux/time.h>
-+
-+/* The 47162a0 hangs when reading MIPS DMP registers registers */
-+static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
-+{
-+	return dev->bus->chipinfo.id == 47162 && dev->bus->chipinfo.rev == 0 &&
-+	       dev->id.id == BCMA_CORE_MIPS_74K;
-+}
-+
-+/* The 5357b0 hangs when reading USB20H DMP registers */
-+static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev)
-+{
-+	return (dev->bus->chipinfo.id == 0x5357 ||
-+		dev->bus->chipinfo.id == 0x4749) &&
-+	       dev->bus->chipinfo.pkg == 11 &&
-+	       dev->id.id == BCMA_CORE_USB20_HOST;
-+}
-+
-+static inline u32 mips_read32(struct bcma_drv_mips *mcore,
-+			      u16 offset)
-+{
-+	return bcma_read32(mcore->core, offset);
-+}
-+
-+static inline void mips_write32(struct bcma_drv_mips *mcore,
-+				u16 offset,
-+				u32 value)
-+{
-+	bcma_write32(mcore->core, offset, value);
-+}
-+
-+static const u32 ipsflag_irq_mask[] = {
-+	0,
-+	BCMA_MIPS_IPSFLAG_IRQ1,
-+	BCMA_MIPS_IPSFLAG_IRQ2,
-+	BCMA_MIPS_IPSFLAG_IRQ3,
-+	BCMA_MIPS_IPSFLAG_IRQ4,
++struct bcma_chipcommon_pmu {
++	u8 rev;			/* PMU revision */
++	u32 crystalfreq;	/* The active crystal frequency (in kHz) */
 +};
 +
-+static const u32 ipsflag_irq_shift[] = {
-+	0,
-+	BCMA_MIPS_IPSFLAG_IRQ1_SHIFT,
-+	BCMA_MIPS_IPSFLAG_IRQ2_SHIFT,
-+	BCMA_MIPS_IPSFLAG_IRQ3_SHIFT,
-+	BCMA_MIPS_IPSFLAG_IRQ4_SHIFT,
++#ifdef CONFIG_BCMA_DRIVER_MIPS
++struct bcma_pflash {
++	u8 buswidth;
++	u32 window;
++	u32 window_size;
 +};
 +
-+static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
-+{
-+	u32 flag;
-+
-+	if (bcma_core_mips_bcm47162a0_quirk(dev))
-+		return dev->core_index;
-+	if (bcma_core_mips_bcm5357b0_quirk(dev))
-+		return dev->core_index;
-+	flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
-+
-+	return flag & 0x1F;
-+}
-+
-+/* Get the MIPS IRQ assignment for a specified device.
-+ * If unassigned, 0 is returned.
-+ */
-+unsigned int bcma_core_mips_irq(struct bcma_device *dev)
-+{
-+	struct bcma_device *mdev = dev->bus->drv_mips.core;
-+	u32 irqflag;
++struct bcma_serial_port {
++	void *regs;
++	unsigned long clockspeed;
 +	unsigned int irq;
++	unsigned int baud_base;
++	unsigned int reg_shift;
++};
++#endif /* CONFIG_BCMA_DRIVER_MIPS */
 +
-+	irqflag = bcma_core_mips_irqflag(dev);
-+
-+	for (irq = 1; irq <= 4; irq++)
-+		if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
-+		    (1 << irqflag))
-+			return irq;
++struct bcma_drv_cc {
++	struct bcma_device *core;
++	u32 status;
++	u32 capabilities;
++	u32 capabilities_ext;
++	u8 setup_done:1;
++	/* Fast Powerup Delay constant */
++	u16 fast_pwrup_delay;
++	struct bcma_chipcommon_pmu pmu;
++#ifdef CONFIG_BCMA_DRIVER_MIPS
++	struct bcma_pflash pflash;
 +
-+	return 0;
-+}
-+EXPORT_SYMBOL(bcma_core_mips_irq);
++	int nr_serial_ports;
++	struct bcma_serial_port serial_ports[4];
++#endif /* CONFIG_BCMA_DRIVER_MIPS */
++};
 +
-+static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
-+{
-+	unsigned int oldirq = bcma_core_mips_irq(dev);
-+	struct bcma_bus *bus = dev->bus;
-+	struct bcma_device *mdev = bus->drv_mips.core;
-+	u32 irqflag;
++/* Register access */
++#define bcma_cc_read32(cc, offset) \
++	bcma_read32((cc)->core, offset)
++#define bcma_cc_write32(cc, offset, val) \
++	bcma_write32((cc)->core, offset, val)
 +
-+	irqflag = bcma_core_mips_irqflag(dev);
-+	BUG_ON(oldirq == 6);
++#define bcma_cc_mask32(cc, offset, mask) \
++	bcma_cc_write32(cc, offset, bcma_cc_read32(cc, offset) & (mask))
++#define bcma_cc_set32(cc, offset, set) \
++	bcma_cc_write32(cc, offset, bcma_cc_read32(cc, offset) | (set))
++#define bcma_cc_maskset32(cc, offset, mask, set) \
++	bcma_cc_write32(cc, offset, (bcma_cc_read32(cc, offset) & (mask)) | (set))
 +
-+	dev->irq = irq + 2;
++extern void bcma_core_chipcommon_init(struct bcma_drv_cc *cc);
 +
-+	/* clear the old irq */
-+	if (oldirq == 0)
-+		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
-+			    bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
-+			    ~(1 << irqflag));
-+	else
-+		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0);
++extern void bcma_chipco_suspend(struct bcma_drv_cc *cc);
++extern void bcma_chipco_resume(struct bcma_drv_cc *cc);
 +
-+	/* assign the new one */
-+	if (irq == 0) {
-+		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
-+			    bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
-+			    (1 << irqflag));
-+	} else {
-+		u32 oldirqflag = bcma_read32(mdev,
-+					     BCMA_MIPS_MIPS74K_INTMASK(irq));
-+		if (oldirqflag) {
-+			struct bcma_device *core;
++void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable);
 +
-+			/* backplane irq line is in use, find out who uses
-+			 * it and set user to irq 0
-+			 */
-+			list_for_each_entry_reverse(core, &bus->cores, list) {
-+				if ((1 << bcma_core_mips_irqflag(core)) ==
-+				    oldirqflag) {
-+					bcma_core_mips_set_irq(core, 0);
-+					break;
-+				}
-+			}
-+		}
-+		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq),
-+			     1 << irqflag);
-+	}
++extern void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc,
++					  u32 ticks);
 +
-+	pr_info("set_irq: core 0x%04x, irq %d => %d\n",
-+		dev->id.id, oldirq + 2, irq + 2);
-+}
++void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value);
 +
-+static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
-+{
-+	int i;
-+	static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
-+	printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
-+	for (i = 0; i <= 6; i++)
-+		printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
-+	printk("\n");
-+}
++u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask);
 +
-+static void bcma_core_mips_dump_irq(struct bcma_bus *bus)
-+{
-+	struct bcma_device *core;
++/* Chipcommon GPIO pin access. */
++u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask);
++u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value);
++u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value);
++u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value);
++u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value);
++u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value);
 +
-+	list_for_each_entry_reverse(core, &bus->cores, list) {
-+		bcma_core_mips_print_irq(core, bcma_core_mips_irq(core));
-+	}
-+}
++/* PMU support */
++extern void bcma_pmu_init(struct bcma_drv_cc *cc);
 +
-+u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
-+{
-+	struct bcma_bus *bus = mcore->core->bus;
++extern void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset,
++				  u32 value);
++extern void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset,
++				    u32 mask, u32 set);
++extern void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
++					u32 offset, u32 mask, u32 set);
++extern void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc,
++				       u32 offset, u32 mask, u32 set);
 +
-+	if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
-+		return bcma_pmu_get_clockcpu(&bus->drv_cc);
++#endif /* LINUX_BCMA_DRIVER_CC_H_ */
+--- /dev/null
++++ b/include/linux/bcma/bcma_driver_mips.h
+@@ -0,0 +1,51 @@
++#ifndef LINUX_BCMA_DRIVER_MIPS_H_
++#define LINUX_BCMA_DRIVER_MIPS_H_
 +
-+	pr_err("No PMU available, need this to get the cpu clock\n");
-+	return 0;
-+}
-+EXPORT_SYMBOL(bcma_cpu_clock);
++#define BCMA_MIPS_IPSFLAG		0x0F08
++/* which sbflags get routed to mips interrupt 1 */
++#define  BCMA_MIPS_IPSFLAG_IRQ1		0x0000003F
++#define  BCMA_MIPS_IPSFLAG_IRQ1_SHIFT	0
++/* which sbflags get routed to mips interrupt 2 */
++#define  BCMA_MIPS_IPSFLAG_IRQ2		0x00003F00
++#define  BCMA_MIPS_IPSFLAG_IRQ2_SHIFT	8
++/* which sbflags get routed to mips interrupt 3 */
++#define  BCMA_MIPS_IPSFLAG_IRQ3		0x003F0000
++#define  BCMA_MIPS_IPSFLAG_IRQ3_SHIFT	16
++/* which sbflags get routed to mips interrupt 4 */
++#define  BCMA_MIPS_IPSFLAG_IRQ4		0x3F000000
++#define  BCMA_MIPS_IPSFLAG_IRQ4_SHIFT	24
 +
-+static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
-+{
-+	struct bcma_bus *bus = mcore->core->bus;
++/* MIPS 74K core registers */
++#define BCMA_MIPS_MIPS74K_CORECTL	0x0000
++#define BCMA_MIPS_MIPS74K_EXCEPTBASE	0x0004
++#define BCMA_MIPS_MIPS74K_BIST		0x000C
++#define BCMA_MIPS_MIPS74K_INTMASK_INT0	0x0014
++#define BCMA_MIPS_MIPS74K_INTMASK(int) \
++	((int) * 4 + BCMA_MIPS_MIPS74K_INTMASK_INT0)
++#define BCMA_MIPS_MIPS74K_NMIMASK	0x002C
++#define BCMA_MIPS_MIPS74K_GPIOSEL	0x0040
++#define BCMA_MIPS_MIPS74K_GPIOOUT	0x0044
++#define BCMA_MIPS_MIPS74K_GPIOEN	0x0048
++#define BCMA_MIPS_MIPS74K_CLKCTLST	0x01E0
 +
-+	switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
-+	case BCMA_CC_FLASHT_STSER:
-+	case BCMA_CC_FLASHT_ATSER:
-+		pr_err("Serial flash not supported.\n");
-+		break;
-+	case BCMA_CC_FLASHT_PARA:
-+		pr_info("found parallel flash.\n");
-+		bus->drv_cc.pflash.window = 0x1c000000;
-+		bus->drv_cc.pflash.window_size = 0x02000000;
++#define BCMA_MIPS_OOBSELOUTA30		0x100
 +
-+		if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) &
-+		     BCMA_CC_FLASH_CFG_DS) == 0)
-+			bus->drv_cc.pflash.buswidth = 1;
-+		else
-+			bus->drv_cc.pflash.buswidth = 2;
-+		break;
-+	default:
-+		pr_err("flash not supported.\n");
-+	}
-+}
++struct bcma_device;
 +
-+void bcma_core_mips_init(struct bcma_drv_mips *mcore)
-+{
-+	struct bcma_bus *bus;
++struct bcma_drv_mips {
 +	struct bcma_device *core;
-+	bus = mcore->core->bus;
-+
-+	pr_info("Initializing MIPS core...\n");
-+
-+	if (!mcore->setup_done)
-+		mcore->assigned_irqs = 1;
++	u8 setup_done:1;
++	unsigned int assigned_irqs;
++};
 +
-+	/* Assign IRQs to all cores on the bus */
-+	list_for_each_entry_reverse(core, &bus->cores, list) {
-+		int mips_irq;
-+		if (core->irq)
-+			continue;
++#ifdef CONFIG_BCMA_DRIVER_MIPS
++extern void bcma_core_mips_init(struct bcma_drv_mips *mcore);
++#else
++static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { }
++#endif
 +
-+		mips_irq = bcma_core_mips_irq(core);
-+		if (mips_irq > 4)
-+			core->irq = 0;
-+		else
-+			core->irq = mips_irq + 2;
-+		if (core->irq > 5)
-+			continue;
-+		switch (core->id.id) {
-+		case BCMA_CORE_PCI:
-+		case BCMA_CORE_PCIE:
-+		case BCMA_CORE_ETHERNET:
-+		case BCMA_CORE_ETHERNET_GBIT:
-+		case BCMA_CORE_MAC_GBIT:
-+		case BCMA_CORE_80211:
-+		case BCMA_CORE_USB20_HOST:
-+			/* These devices get their own IRQ line if available,
-+			 * the rest goes on IRQ0
-+			 */
-+			if (mcore->assigned_irqs <= 4)
-+				bcma_core_mips_set_irq(core,
-+						       mcore->assigned_irqs++);
-+			break;
-+		}
-+	}
-+	pr_info("IRQ reconfiguration done\n");
-+	bcma_core_mips_dump_irq(bus);
++extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore);
 +
-+	if (mcore->setup_done)
-+		return;
++extern unsigned int bcma_core_mips_irq(struct bcma_device *dev);
 +
-+	bcma_chipco_serial_init(&bus->drv_cc);
-+	bcma_core_mips_flash_detect(mcore);
-+	mcore->setup_done = true;
-+}
++#endif /* LINUX_BCMA_DRIVER_MIPS_H_ */
 --- /dev/null
-+++ b/drivers/bcma/host_soc.c
-@@ -0,0 +1,183 @@
-+/*
-+ * Broadcom specific AMBA
-+ * System on Chip (SoC) Host
-+ *
-+ * Licensed under the GNU/GPL. See COPYING for details.
-+ */
-+
-+#include "bcma_private.h"
-+#include "scan.h"
-+#include <linux/bcma/bcma.h>
-+#include <linux/bcma/bcma_soc.h>
-+
-+static u8 bcma_host_soc_read8(struct bcma_device *core, u16 offset)
-+{
-+	return readb(core->io_addr + offset);
-+}
-+
-+static u16 bcma_host_soc_read16(struct bcma_device *core, u16 offset)
-+{
-+	return readw(core->io_addr + offset);
-+}
++++ b/include/linux/bcma/bcma_driver_pci.h
+@@ -0,0 +1,225 @@
++#ifndef LINUX_BCMA_DRIVER_PCI_H_
++#define LINUX_BCMA_DRIVER_PCI_H_
 +
-+static u32 bcma_host_soc_read32(struct bcma_device *core, u16 offset)
-+{
-+	return readl(core->io_addr + offset);
-+}
++#include <linux/types.h>
 +
-+static void bcma_host_soc_write8(struct bcma_device *core, u16 offset,
-+				 u8 value)
-+{
-+	writeb(value, core->io_addr + offset);
-+}
++struct pci_dev;
 +
-+static void bcma_host_soc_write16(struct bcma_device *core, u16 offset,
-+				 u16 value)
-+{
-+	writew(value, core->io_addr + offset);
-+}
++/** PCI core registers. **/
++#define BCMA_CORE_PCI_CTL			0x0000	/* PCI Control */
++#define  BCMA_CORE_PCI_CTL_RST_OE		0x00000001 /* PCI_RESET Output Enable */
++#define  BCMA_CORE_PCI_CTL_RST			0x00000002 /* PCI_RESET driven out to pin */
++#define  BCMA_CORE_PCI_CTL_CLK_OE		0x00000004 /* Clock gate Output Enable */
++#define  BCMA_CORE_PCI_CTL_CLK			0x00000008 /* Gate for clock driven out to pin */
++#define BCMA_CORE_PCI_ARBCTL			0x0010	/* PCI Arbiter Control */
++#define  BCMA_CORE_PCI_ARBCTL_INTERN		0x00000001 /* Use internal arbiter */
++#define  BCMA_CORE_PCI_ARBCTL_EXTERN		0x00000002 /* Use external arbiter */
++#define  BCMA_CORE_PCI_ARBCTL_PARKID		0x00000006 /* Mask, selects which agent is parked on an idle bus */
++#define   BCMA_CORE_PCI_ARBCTL_PARKID_LAST	0x00000000 /* Last requestor */
++#define   BCMA_CORE_PCI_ARBCTL_PARKID_4710	0x00000002 /* 4710 */
++#define   BCMA_CORE_PCI_ARBCTL_PARKID_EXT0	0x00000004 /* External requestor 0 */
++#define   BCMA_CORE_PCI_ARBCTL_PARKID_EXT1	0x00000006 /* External requestor 1 */
++#define BCMA_CORE_PCI_ISTAT			0x0020	/* Interrupt status */
++#define  BCMA_CORE_PCI_ISTAT_INTA		0x00000001 /* PCI INTA# */
++#define  BCMA_CORE_PCI_ISTAT_INTB		0x00000002 /* PCI INTB# */
++#define  BCMA_CORE_PCI_ISTAT_SERR		0x00000004 /* PCI SERR# (write to clear) */
++#define  BCMA_CORE_PCI_ISTAT_PERR		0x00000008 /* PCI PERR# (write to clear) */
++#define  BCMA_CORE_PCI_ISTAT_PME		0x00000010 /* PCI PME# */
++#define BCMA_CORE_PCI_IMASK			0x0024	/* Interrupt mask */
++#define  BCMA_CORE_PCI_IMASK_INTA		0x00000001 /* PCI INTA# */
++#define  BCMA_CORE_PCI_IMASK_INTB		0x00000002 /* PCI INTB# */
++#define  BCMA_CORE_PCI_IMASK_SERR		0x00000004 /* PCI SERR# */
++#define  BCMA_CORE_PCI_IMASK_PERR		0x00000008 /* PCI PERR# */
++#define  BCMA_CORE_PCI_IMASK_PME		0x00000010 /* PCI PME# */
++#define BCMA_CORE_PCI_MBOX			0x0028	/* Backplane to PCI Mailbox */
++#define  BCMA_CORE_PCI_MBOX_F0_0		0x00000100 /* PCI function 0, INT 0 */
++#define  BCMA_CORE_PCI_MBOX_F0_1		0x00000200 /* PCI function 0, INT 1 */
++#define  BCMA_CORE_PCI_MBOX_F1_0		0x00000400 /* PCI function 1, INT 0 */
++#define  BCMA_CORE_PCI_MBOX_F1_1		0x00000800 /* PCI function 1, INT 1 */
++#define  BCMA_CORE_PCI_MBOX_F2_0		0x00001000 /* PCI function 2, INT 0 */
++#define  BCMA_CORE_PCI_MBOX_F2_1		0x00002000 /* PCI function 2, INT 1 */
++#define  BCMA_CORE_PCI_MBOX_F3_0		0x00004000 /* PCI function 3, INT 0 */
++#define  BCMA_CORE_PCI_MBOX_F3_1		0x00008000 /* PCI function 3, INT 1 */
++#define BCMA_CORE_PCI_BCAST_ADDR		0x0050	/* Backplane Broadcast Address */
++#define  BCMA_CORE_PCI_BCAST_ADDR_MASK		0x000000FF
++#define BCMA_CORE_PCI_BCAST_DATA		0x0054	/* Backplane Broadcast Data */
++#define BCMA_CORE_PCI_GPIO_IN			0x0060	/* rev >= 2 only */
++#define BCMA_CORE_PCI_GPIO_OUT			0x0064	/* rev >= 2 only */
++#define BCMA_CORE_PCI_GPIO_ENABLE		0x0068	/* rev >= 2 only */
++#define BCMA_CORE_PCI_GPIO_CTL			0x006C	/* rev >= 2 only */
++#define BCMA_CORE_PCI_SBTOPCI0			0x0100	/* Backplane to PCI translation 0 (sbtopci0) */
++#define  BCMA_CORE_PCI_SBTOPCI0_MASK		0xFC000000
++#define BCMA_CORE_PCI_SBTOPCI1			0x0104	/* Backplane to PCI translation 1 (sbtopci1) */
++#define  BCMA_CORE_PCI_SBTOPCI1_MASK		0xFC000000
++#define BCMA_CORE_PCI_SBTOPCI2			0x0108	/* Backplane to PCI translation 2 (sbtopci2) */
++#define  BCMA_CORE_PCI_SBTOPCI2_MASK		0xC0000000
++#define BCMA_CORE_PCI_CONFIG_ADDR		0x0120	/* pcie config space access */
++#define BCMA_CORE_PCI_CONFIG_DATA		0x0124	/* pcie config space access */
++#define BCMA_CORE_PCI_MDIO_CONTROL		0x0128	/* controls the mdio access */
++#define  BCMA_CORE_PCI_MDIOCTL_DIVISOR_MASK	0x7f	/* clock to be used on MDIO */
++#define  BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL	0x2
++#define  BCMA_CORE_PCI_MDIOCTL_PREAM_EN		0x80	/* Enable preamble sequnce */
++#define  BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE	0x100	/* Tranaction complete */
++#define BCMA_CORE_PCI_MDIO_DATA			0x012c	/* Data to the mdio access */
++#define  BCMA_CORE_PCI_MDIODATA_MASK		0x0000ffff /* data 2 bytes */
++#define  BCMA_CORE_PCI_MDIODATA_TA		0x00020000 /* Turnaround */
++#define  BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD	18	/* Regaddr shift (rev < 10) */
++#define  BCMA_CORE_PCI_MDIODATA_REGADDR_MASK_OLD	0x003c0000 /* Regaddr Mask (rev < 10) */
++#define  BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD	22	/* Physmedia devaddr shift (rev < 10) */
++#define  BCMA_CORE_PCI_MDIODATA_DEVADDR_MASK_OLD	0x0fc00000 /* Physmedia devaddr Mask (rev < 10) */
++#define  BCMA_CORE_PCI_MDIODATA_REGADDR_SHF	18	/* Regaddr shift */
++#define  BCMA_CORE_PCI_MDIODATA_REGADDR_MASK	0x007c0000 /* Regaddr Mask */
++#define  BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF	23	/* Physmedia devaddr shift */
++#define  BCMA_CORE_PCI_MDIODATA_DEVADDR_MASK	0x0f800000 /* Physmedia devaddr Mask */
++#define  BCMA_CORE_PCI_MDIODATA_WRITE		0x10000000 /* write Transaction */
++#define  BCMA_CORE_PCI_MDIODATA_READ		0x20000000 /* Read Transaction */
++#define  BCMA_CORE_PCI_MDIODATA_START		0x40000000 /* start of Transaction */
++#define  BCMA_CORE_PCI_MDIODATA_DEV_ADDR	0x0	/* dev address for serdes */
++#define  BCMA_CORE_PCI_MDIODATA_BLK_ADDR	0x1F	/* blk address for serdes */
++#define  BCMA_CORE_PCI_MDIODATA_DEV_PLL		0x1d	/* SERDES PLL Dev */
++#define  BCMA_CORE_PCI_MDIODATA_DEV_TX		0x1e	/* SERDES TX Dev */
++#define  BCMA_CORE_PCI_MDIODATA_DEV_RX		0x1f	/* SERDES RX Dev */
++#define BCMA_CORE_PCI_PCIEIND_ADDR		0x0130	/* indirect access to the internal register */
++#define BCMA_CORE_PCI_PCIEIND_DATA		0x0134	/* Data to/from the internal regsiter */
++#define BCMA_CORE_PCI_CLKREQENCTRL		0x0138	/*  >= rev 6, Clkreq rdma control */
++#define BCMA_CORE_PCI_PCICFG0			0x0400	/* PCI config space 0 (rev >= 8) */
++#define BCMA_CORE_PCI_PCICFG1			0x0500	/* PCI config space 1 (rev >= 8) */
++#define BCMA_CORE_PCI_PCICFG2			0x0600	/* PCI config space 2 (rev >= 8) */
++#define BCMA_CORE_PCI_PCICFG3			0x0700	/* PCI config space 3 (rev >= 8) */
++#define BCMA_CORE_PCI_SPROM(wordoffset)		(0x0800 + ((wordoffset) * 2)) /* SPROM shadow area (72 bytes) */
++#define  BCMA_CORE_PCI_SPROM_PI_OFFSET		0	/* first word */
++#define   BCMA_CORE_PCI_SPROM_PI_MASK		0xf000	/* bit 15:12 */
++#define   BCMA_CORE_PCI_SPROM_PI_SHIFT		12	/* bit 15:12 */
++#define  BCMA_CORE_PCI_SPROM_MISC_CONFIG	5	/* word 5 */
++#define   BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST	0x8000	/* bit 15 */
++#define   BCMA_CORE_PCI_SPROM_CLKREQ_OFFSET_REV5	20	/* word 20 for srom rev <= 5 */
++#define   BCMA_CORE_PCI_SPROM_CLKREQ_ENB	0x0800	/* bit 11 */
 +
-+static void bcma_host_soc_write32(struct bcma_device *core, u16 offset,
-+				 u32 value)
-+{
-+	writel(value, core->io_addr + offset);
-+}
++/* SBtoPCIx */
++#define BCMA_CORE_PCI_SBTOPCI_MEM		0x00000000
++#define BCMA_CORE_PCI_SBTOPCI_IO		0x00000001
++#define BCMA_CORE_PCI_SBTOPCI_CFG0		0x00000002
++#define BCMA_CORE_PCI_SBTOPCI_CFG1		0x00000003
++#define BCMA_CORE_PCI_SBTOPCI_PREF		0x00000004 /* Prefetch enable */
++#define BCMA_CORE_PCI_SBTOPCI_BURST		0x00000008 /* Burst enable */
++#define BCMA_CORE_PCI_SBTOPCI_MRM		0x00000020 /* Memory Read Multiple */
++#define BCMA_CORE_PCI_SBTOPCI_RC		0x00000030 /* Read Command mask (rev >= 11) */
++#define  BCMA_CORE_PCI_SBTOPCI_RC_READ		0x00000000 /* Memory read */
++#define  BCMA_CORE_PCI_SBTOPCI_RC_READL		0x00000010 /* Memory read line */
++#define  BCMA_CORE_PCI_SBTOPCI_RC_READM		0x00000020 /* Memory read multiple */
 +
-+#ifdef CONFIG_BCMA_BLOCKIO
-+static void bcma_host_soc_block_read(struct bcma_device *core, void *buffer,
-+				     size_t count, u16 offset, u8 reg_width)
-+{
-+	void __iomem *addr = core->io_addr + offset;
++/* PCIE protocol PHY diagnostic registers */
++#define BCMA_CORE_PCI_PLP_MODEREG		0x200	/* Mode */
++#define BCMA_CORE_PCI_PLP_STATUSREG		0x204	/* Status */
++#define  BCMA_CORE_PCI_PLP_POLARITYINV_STAT	0x10	/* Status reg PCIE_PLP_STATUSREG */
++#define BCMA_CORE_PCI_PLP_LTSSMCTRLREG		0x208	/* LTSSM control */
++#define BCMA_CORE_PCI_PLP_LTLINKNUMREG		0x20c	/* Link Training Link number */
++#define BCMA_CORE_PCI_PLP_LTLANENUMREG		0x210	/* Link Training Lane number */
++#define BCMA_CORE_PCI_PLP_LTNFTSREG		0x214	/* Link Training N_FTS */
++#define BCMA_CORE_PCI_PLP_ATTNREG		0x218	/* Attention */
++#define BCMA_CORE_PCI_PLP_ATTNMASKREG		0x21C	/* Attention Mask */
++#define BCMA_CORE_PCI_PLP_RXERRCTR		0x220	/* Rx Error */
++#define BCMA_CORE_PCI_PLP_RXFRMERRCTR		0x224	/* Rx Framing Error */
++#define BCMA_CORE_PCI_PLP_RXERRTHRESHREG	0x228	/* Rx Error threshold */
++#define BCMA_CORE_PCI_PLP_TESTCTRLREG		0x22C	/* Test Control reg */
++#define BCMA_CORE_PCI_PLP_SERDESCTRLOVRDREG	0x230	/* SERDES Control Override */
++#define BCMA_CORE_PCI_PLP_TIMINGOVRDREG		0x234	/* Timing param override */
++#define BCMA_CORE_PCI_PLP_RXTXSMDIAGREG		0x238	/* RXTX State Machine Diag */
++#define BCMA_CORE_PCI_PLP_LTSSMDIAGREG		0x23C	/* LTSSM State Machine Diag */
 +
-+	switch (reg_width) {
-+	case sizeof(u8): {
-+		u8 *buf = buffer;
++/* PCIE protocol DLLP diagnostic registers */
++#define BCMA_CORE_PCI_DLLP_LCREG		0x100	/* Link Control */
++#define BCMA_CORE_PCI_DLLP_LSREG		0x104	/* Link Status */
++#define BCMA_CORE_PCI_DLLP_LAREG		0x108	/* Link Attention */
++#define  BCMA_CORE_PCI_DLLP_LSREG_LINKUP	(1 << 16)
++#define BCMA_CORE_PCI_DLLP_LAMASKREG		0x10C	/* Link Attention Mask */
++#define BCMA_CORE_PCI_DLLP_NEXTTXSEQNUMREG	0x110	/* Next Tx Seq Num */
++#define BCMA_CORE_PCI_DLLP_ACKEDTXSEQNUMREG	0x114	/* Acked Tx Seq Num */
++#define BCMA_CORE_PCI_DLLP_PURGEDTXSEQNUMREG	0x118	/* Purged Tx Seq Num */
++#define BCMA_CORE_PCI_DLLP_RXSEQNUMREG		0x11C	/* Rx Sequence Number */
++#define BCMA_CORE_PCI_DLLP_LRREG		0x120	/* Link Replay */
++#define BCMA_CORE_PCI_DLLP_LACKTOREG		0x124	/* Link Ack Timeout */
++#define BCMA_CORE_PCI_DLLP_PMTHRESHREG		0x128	/* Power Management Threshold */
++#define  BCMA_CORE_PCI_ASPMTIMER_EXTEND		0x01000000 /* > rev7: enable extend ASPM timer */
++#define BCMA_CORE_PCI_DLLP_RTRYWPREG		0x12C	/* Retry buffer write ptr */
++#define BCMA_CORE_PCI_DLLP_RTRYRPREG		0x130	/* Retry buffer Read ptr */
++#define BCMA_CORE_PCI_DLLP_RTRYPPREG		0x134	/* Retry buffer Purged ptr */
++#define BCMA_CORE_PCI_DLLP_RTRRWREG		0x138	/* Retry buffer Read/Write */
++#define BCMA_CORE_PCI_DLLP_ECTHRESHREG		0x13C	/* Error Count Threshold */
++#define BCMA_CORE_PCI_DLLP_TLPERRCTRREG		0x140	/* TLP Error Counter */
++#define BCMA_CORE_PCI_DLLP_ERRCTRREG		0x144	/* Error Counter */
++#define BCMA_CORE_PCI_DLLP_NAKRXCTRREG		0x148	/* NAK Received Counter */
++#define BCMA_CORE_PCI_DLLP_TESTREG		0x14C	/* Test */
++#define BCMA_CORE_PCI_DLLP_PKTBIST		0x150	/* Packet BIST */
++#define BCMA_CORE_PCI_DLLP_PCIE11		0x154	/* DLLP PCIE 1.1 reg */
 +
-+		while (count) {
-+			*buf = __raw_readb(addr);
-+			buf++;
-+			count--;
-+		}
-+		break;
-+	}
-+	case sizeof(u16): {
-+		__le16 *buf = buffer;
++/* SERDES RX registers */
++#define BCMA_CORE_PCI_SERDES_RX_CTRL		1	/* Rx cntrl */
++#define  BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE	0x80	/* rxpolarity_force */
++#define  BCMA_CORE_PCI_SERDES_RX_CTRL_POLARITY	0x40	/* rxpolarity_value */
++#define BCMA_CORE_PCI_SERDES_RX_TIMER1		2	/* Rx Timer1 */
++#define BCMA_CORE_PCI_SERDES_RX_CDR		6	/* CDR */
++#define BCMA_CORE_PCI_SERDES_RX_CDRBW		7	/* CDR BW */
 +
-+		WARN_ON(count & 1);
-+		while (count) {
-+			*buf = (__force __le16)__raw_readw(addr);
-+			buf++;
-+			count -= 2;
-+		}
-+		break;
-+	}
-+	case sizeof(u32): {
-+		__le32 *buf = buffer;
++/* SERDES PLL registers */
++#define BCMA_CORE_PCI_SERDES_PLL_CTRL		1	/* PLL control reg */
++#define BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN	0x4000	/* bit 14 is FREQDET on */
 +
-+		WARN_ON(count & 3);
-+		while (count) {
-+			*buf = (__force __le32)__raw_readl(addr);
-+			buf++;
-+			count -= 4;
-+		}
-+		break;
-+	}
-+	default:
-+		WARN_ON(1);
-+	}
-+}
++/* PCIcore specific boardflags */
++#define BCMA_CORE_PCI_BFL_NOPCI			0x00000400 /* Board leaves PCI floating */
 +
-+static void bcma_host_soc_block_write(struct bcma_device *core,
-+				      const void *buffer,
-+				      size_t count, u16 offset, u8 reg_width)
-+{
-+	void __iomem *addr = core->io_addr + offset;
++/* PCIE Config space accessing MACROS */
++#define BCMA_CORE_PCI_CFG_BUS_SHIFT		24	/* Bus shift */
++#define BCMA_CORE_PCI_CFG_SLOT_SHIFT		19	/* Slot/Device shift */
++#define BCMA_CORE_PCI_CFG_FUN_SHIFT		16	/* Function shift */
++#define BCMA_CORE_PCI_CFG_OFF_SHIFT		0	/* Register shift */
 +
-+	switch (reg_width) {
-+	case sizeof(u8): {
-+		const u8 *buf = buffer;
++#define BCMA_CORE_PCI_CFG_BUS_MASK		0xff	/* Bus mask */
++#define BCMA_CORE_PCI_CFG_SLOT_MASK		0x1f	/* Slot/Device mask */
++#define BCMA_CORE_PCI_CFG_FUN_MASK		7	/* Function mask */
++#define BCMA_CORE_PCI_CFG_OFF_MASK		0xfff	/* Register mask */
 +
-+		while (count) {
-+			__raw_writeb(*buf, addr);
-+			buf++;
-+			count--;
-+		}
-+		break;
-+	}
-+	case sizeof(u16): {
-+		const __le16 *buf = buffer;
++/* PCIE Root Capability Register bits (Host mode only) */
++#define BCMA_CORE_PCI_RC_CRS_VISIBILITY		0x0001
 +
-+		WARN_ON(count & 1);
-+		while (count) {
-+			__raw_writew((__force u16)(*buf), addr);
-+			buf++;
-+			count -= 2;
-+		}
-+		break;
-+	}
-+	case sizeof(u32): {
-+		const __le32 *buf = buffer;
++struct bcma_drv_pci;
 +
-+		WARN_ON(count & 3);
-+		while (count) {
-+			__raw_writel((__force u32)(*buf), addr);
-+			buf++;
-+			count -= 4;
-+		}
-+		break;
-+	}
-+	default:
-+		WARN_ON(1);
-+	}
-+}
-+#endif /* CONFIG_BCMA_BLOCKIO */
++#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
++struct bcma_drv_pci_host {
++	struct bcma_drv_pci *pdev;
 +
-+static u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset)
-+{
-+	return readl(core->io_wrap + offset);
-+}
++	u32 host_cfg_addr;
++	spinlock_t cfgspace_lock;
 +
-+static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
-+				  u32 value)
-+{
-+	writel(value, core->io_wrap + offset);
-+}
++	struct pci_controller pci_controller;
++	struct pci_ops pci_ops;
++	struct resource mem_resource;
++	struct resource io_resource;
++};
++#endif
 +
-+const struct bcma_host_ops bcma_host_soc_ops = {
-+	.read8		= bcma_host_soc_read8,
-+	.read16		= bcma_host_soc_read16,
-+	.read32		= bcma_host_soc_read32,
-+	.write8		= bcma_host_soc_write8,
-+	.write16	= bcma_host_soc_write16,
-+	.write32	= bcma_host_soc_write32,
-+#ifdef CONFIG_BCMA_BLOCKIO
-+	.block_read	= bcma_host_soc_block_read,
-+	.block_write	= bcma_host_soc_block_write,
++struct bcma_drv_pci {
++	struct bcma_device *core;
++	u8 setup_done:1;
++	u8 hostmode:1;
++
++#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
++	struct bcma_drv_pci_host *host_controller;
 +#endif
-+	.aread32	= bcma_host_soc_aread32,
-+	.awrite32	= bcma_host_soc_awrite32,
 +};
 +
-+int __init bcma_host_soc_register(struct bcma_soc *soc)
-+{
-+	struct bcma_bus *bus = &soc->bus;
-+	int err;
-+
-+	/* iomap only first core. We have to read some register on this core
-+	 * to scan the bus.
-+	 */
-+	bus->mmio = ioremap_nocache(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
-+	if (!bus->mmio)
-+		return -ENOMEM;
++/* Register access */
++#define pcicore_read16(pc, offset)		bcma_read16((pc)->core, offset)
++#define pcicore_read32(pc, offset)		bcma_read32((pc)->core, offset)
++#define pcicore_write16(pc, offset, val)	bcma_write16((pc)->core, offset, val)
++#define pcicore_write32(pc, offset, val)	bcma_write32((pc)->core, offset, val)
 +
-+	/* Host specific */
-+	bus->hosttype = BCMA_HOSTTYPE_SOC;
-+	bus->ops = &bcma_host_soc_ops;
++extern void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc);
++extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
++				 struct bcma_device *core, bool enable);
++extern void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend);
 +
-+	/* Register */
-+	err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips);
-+	if (err)
-+		iounmap(bus->mmio);
++extern int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev);
++extern int bcma_core_pci_plat_dev_init(struct pci_dev *dev);
 +
-+	return err;
-+}
++#endif /* LINUX_BCMA_DRIVER_PCI_H_ */
 --- /dev/null
-+++ b/include/linux/bcma/bcma_driver_mips.h
-@@ -0,0 +1,51 @@
-+#ifndef LINUX_BCMA_DRIVER_MIPS_H_
-+#define LINUX_BCMA_DRIVER_MIPS_H_
-+
-+#define BCMA_MIPS_IPSFLAG		0x0F08
-+/* which sbflags get routed to mips interrupt 1 */
-+#define  BCMA_MIPS_IPSFLAG_IRQ1		0x0000003F
-+#define  BCMA_MIPS_IPSFLAG_IRQ1_SHIFT	0
-+/* which sbflags get routed to mips interrupt 2 */
-+#define  BCMA_MIPS_IPSFLAG_IRQ2		0x00003F00
-+#define  BCMA_MIPS_IPSFLAG_IRQ2_SHIFT	8
-+/* which sbflags get routed to mips interrupt 3 */
-+#define  BCMA_MIPS_IPSFLAG_IRQ3		0x003F0000
-+#define  BCMA_MIPS_IPSFLAG_IRQ3_SHIFT	16
-+/* which sbflags get routed to mips interrupt 4 */
-+#define  BCMA_MIPS_IPSFLAG_IRQ4		0x3F000000
-+#define  BCMA_MIPS_IPSFLAG_IRQ4_SHIFT	24
++++ b/include/linux/bcma/bcma_regs.h
+@@ -0,0 +1,86 @@
++#ifndef LINUX_BCMA_REGS_H_
++#define LINUX_BCMA_REGS_H_
 +
-+/* MIPS 74K core registers */
-+#define BCMA_MIPS_MIPS74K_CORECTL	0x0000
-+#define BCMA_MIPS_MIPS74K_EXCEPTBASE	0x0004
-+#define BCMA_MIPS_MIPS74K_BIST		0x000C
-+#define BCMA_MIPS_MIPS74K_INTMASK_INT0	0x0014
-+#define BCMA_MIPS_MIPS74K_INTMASK(int) \
-+	((int) * 4 + BCMA_MIPS_MIPS74K_INTMASK_INT0)
-+#define BCMA_MIPS_MIPS74K_NMIMASK	0x002C
-+#define BCMA_MIPS_MIPS74K_GPIOSEL	0x0040
-+#define BCMA_MIPS_MIPS74K_GPIOOUT	0x0044
-+#define BCMA_MIPS_MIPS74K_GPIOEN	0x0048
-+#define BCMA_MIPS_MIPS74K_CLKCTLST	0x01E0
++/* Some single registers are shared between many cores */
++/* BCMA_CLKCTLST: ChipCommon (rev >= 20), PCIe, 80211 */
++#define BCMA_CLKCTLST			0x01E0 /* Clock control and status */
++#define  BCMA_CLKCTLST_FORCEALP		0x00000001 /* Force ALP request */
++#define  BCMA_CLKCTLST_FORCEHT		0x00000002 /* Force HT request */
++#define  BCMA_CLKCTLST_FORCEILP		0x00000004 /* Force ILP request */
++#define  BCMA_CLKCTLST_HAVEALPREQ	0x00000008 /* ALP available request */
++#define  BCMA_CLKCTLST_HAVEHTREQ	0x00000010 /* HT available request */
++#define  BCMA_CLKCTLST_HWCROFF		0x00000020 /* Force HW clock request off */
++#define  BCMA_CLKCTLST_EXTRESREQ	0x00000700 /* Mask of external resource requests */
++#define  BCMA_CLKCTLST_HAVEALP		0x00010000 /* ALP available */
++#define  BCMA_CLKCTLST_HAVEHT		0x00020000 /* HT available */
++#define  BCMA_CLKCTLST_BP_ON_ALP	0x00040000 /* RO: running on ALP clock */
++#define  BCMA_CLKCTLST_BP_ON_HT		0x00080000 /* RO: running on HT clock */
++#define  BCMA_CLKCTLST_EXTRESST		0x07000000 /* Mask of external resource status */
++/* Is there any BCM4328 on BCMA bus? */
++#define  BCMA_CLKCTLST_4328A0_HAVEHT	0x00010000 /* 4328a0 has reversed bits */
++#define  BCMA_CLKCTLST_4328A0_HAVEALP	0x00020000 /* 4328a0 has reversed bits */
 +
-+#define BCMA_MIPS_OOBSELOUTA30		0x100
++/* Agent registers (common for every core) */
++#define BCMA_IOCTL			0x0408 /* IO control */
++#define  BCMA_IOCTL_CLK			0x0001
++#define  BCMA_IOCTL_FGC			0x0002
++#define  BCMA_IOCTL_CORE_BITS		0x3FFC
++#define  BCMA_IOCTL_PME_EN		0x4000
++#define  BCMA_IOCTL_BIST_EN		0x8000
++#define BCMA_IOST			0x0500 /* IO status */
++#define  BCMA_IOST_CORE_BITS		0x0FFF
++#define  BCMA_IOST_DMA64		0x1000
++#define  BCMA_IOST_GATED_CLK		0x2000
++#define  BCMA_IOST_BIST_ERROR		0x4000
++#define  BCMA_IOST_BIST_DONE		0x8000
++#define BCMA_RESET_CTL			0x0800
++#define  BCMA_RESET_CTL_RESET		0x0001
 +
-+struct bcma_device;
++/* BCMA PCI config space registers. */
++#define BCMA_PCI_PMCSR			0x44
++#define  BCMA_PCI_PE			0x100
++#define BCMA_PCI_BAR0_WIN		0x80	/* Backplane address space 0 */
++#define BCMA_PCI_BAR1_WIN		0x84	/* Backplane address space 1 */
++#define BCMA_PCI_SPROMCTL		0x88	/* SPROM control */
++#define  BCMA_PCI_SPROMCTL_WE		0x10	/* SPROM write enable */
++#define BCMA_PCI_BAR1_CONTROL		0x8c	/* Address space 1 burst control */
++#define BCMA_PCI_IRQS			0x90	/* PCI interrupts */
++#define BCMA_PCI_IRQMASK		0x94	/* PCI IRQ control and mask (pcirev >= 6 only) */
++#define BCMA_PCI_BACKPLANE_IRQS		0x98	/* Backplane Interrupts */
++#define BCMA_PCI_BAR0_WIN2		0xAC
++#define BCMA_PCI_GPIO_IN		0xB0	/* GPIO Input (pcirev >= 3 only) */
++#define BCMA_PCI_GPIO_OUT		0xB4	/* GPIO Output (pcirev >= 3 only) */
++#define BCMA_PCI_GPIO_OUT_ENABLE	0xB8	/* GPIO Output Enable/Disable (pcirev >= 3 only) */
++#define  BCMA_PCI_GPIO_SCS		0x10	/* PCI config space bit 4 for 4306c0 slow clock source */
++#define  BCMA_PCI_GPIO_HWRAD		0x20	/* PCI config space GPIO 13 for hw radio disable */
++#define  BCMA_PCI_GPIO_XTAL		0x40	/* PCI config space GPIO 14 for Xtal powerup */
++#define  BCMA_PCI_GPIO_PLL		0x80	/* PCI config space GPIO 15 for PLL powerdown */
 +
-+struct bcma_drv_mips {
-+	struct bcma_device *core;
-+	u8 setup_done:1;
-+	unsigned int assigned_irqs;
-+};
++/* SiliconBackplane Address Map.
++ * All regions may not exist on all chips.
++ */
++#define BCMA_SOC_SDRAM_BASE		0x00000000U	/* Physical SDRAM */
++#define BCMA_SOC_PCI_MEM		0x08000000U	/* Host Mode sb2pcitranslation0 (64 MB) */
++#define BCMA_SOC_PCI_MEM_SZ		(64 * 1024 * 1024)
++#define BCMA_SOC_PCI_CFG		0x0c000000U	/* Host Mode sb2pcitranslation1 (64 MB) */
++#define BCMA_SOC_SDRAM_SWAPPED		0x10000000U	/* Byteswapped Physical SDRAM */
++#define BCMA_SOC_SDRAM_R2		0x80000000U	/* Region 2 for sdram (512 MB) */
 +
-+#ifdef CONFIG_BCMA_DRIVER_MIPS
-+extern void bcma_core_mips_init(struct bcma_drv_mips *mcore);
-+#else
-+static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { }
-+#endif
 +
-+extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore);
++#define BCMA_SOC_PCI_DMA		0x40000000U	/* Client Mode sb2pcitranslation2 (1 GB) */
++#define BCMA_SOC_PCI_DMA2		0x80000000U	/* Client Mode sb2pcitranslation2 (1 GB) */
++#define BCMA_SOC_PCI_DMA_SZ		0x40000000U	/* Client Mode sb2pcitranslation2 size in bytes */
++#define BCMA_SOC_PCIE_DMA_L32		0x00000000U	/* PCIE Client Mode sb2pcitranslation2
++							 * (2 ZettaBytes), low 32 bits
++							 */
++#define BCMA_SOC_PCIE_DMA_H32		0x80000000U	/* PCIE Client Mode sb2pcitranslation2
++							 * (2 ZettaBytes), high 32 bits
++							 */
 +
-+extern unsigned int bcma_core_mips_irq(struct bcma_device *dev);
++#define BCMA_SOC_PCI1_MEM		0x40000000U	/* Host Mode sb2pcitranslation0 (64 MB) */
++#define BCMA_SOC_PCI1_CFG		0x44000000U	/* Host Mode sb2pcitranslation1 (64 MB) */
++#define BCMA_SOC_PCIE1_DMA_H32		0xc0000000U	/* PCIE Client Mode sb2pcitranslation2
++							 * (2 ZettaBytes), high 32 bits
++							 */
 +
-+#endif /* LINUX_BCMA_DRIVER_MIPS_H_ */
++#endif /* LINUX_BCMA_REGS_H_ */
 --- /dev/null
 +++ b/include/linux/bcma/bcma_soc.h
 @@ -0,0 +1,16 @@
@@ -4976,3 +5158,67 @@
 +int bcma_bus_register(struct bcma_bus *bus);
 +
 +#endif /* LINUX_BCMA_SOC_H_ */
+--- a/include/linux/mod_devicetable.h
++++ b/include/linux/mod_devicetable.h
+@@ -382,6 +382,23 @@ struct ssb_device_id {
+ #define SSB_ANY_ID		0xFFFF
+ #define SSB_ANY_REV		0xFF
+ 
++/* Broadcom's specific AMBA core, see drivers/bcma/ */
++struct bcma_device_id {
++	__u16	manuf;
++	__u16	id;
++	__u8	rev;
++	__u8	class;
++};
++#define BCMA_CORE(_manuf, _id, _rev, _class)  \
++	{ .manuf = _manuf, .id = _id, .rev = _rev, .class = _class, }
++#define BCMA_CORETABLE_END  \
++	{ 0, },
++
++#define BCMA_ANY_MANUF		0xFFFF
++#define BCMA_ANY_ID		0xFFFF
++#define BCMA_ANY_REV		0xFF
++#define BCMA_ANY_CLASS		0xFF
++
+ struct virtio_device_id {
+ 	__u32 device;
+ 	__u32 vendor;
+--- a/scripts/mod/file2alias.c
++++ b/scripts/mod/file2alias.c
+@@ -702,6 +702,24 @@ static int do_ssb_entry(const char *file
+ 	return 1;
+ }
+ 
++/* Looks like: bcma:mNidNrevNclN. */
++static int do_bcma_entry(const char *filename,
++			 struct bcma_device_id *id, char *alias)
++{
++	id->manuf = TO_NATIVE(id->manuf);
++	id->id = TO_NATIVE(id->id);
++	id->rev = TO_NATIVE(id->rev);
++	id->class = TO_NATIVE(id->class);
++
++	strcpy(alias, "bcma:");
++	ADD(alias, "m", id->manuf != BCMA_ANY_MANUF, id->manuf);
++	ADD(alias, "id", id->id != BCMA_ANY_ID, id->id);
++	ADD(alias, "rev", id->rev != BCMA_ANY_REV, id->rev);
++	ADD(alias, "cl", id->class != BCMA_ANY_CLASS, id->class);
++	add_wildcard(alias);
++	return 1;
++}
++
+ /* Looks like: virtio:dNvN */
+ static int do_virtio_entry(const char *filename, struct virtio_device_id *id,
+ 			   char *alias)
+@@ -968,6 +986,10 @@ void handle_moddevtable(struct module *m
+ 		do_table(symval, sym->st_size,
+ 			 sizeof(struct ssb_device_id), "ssb",
+ 			 do_ssb_entry, mod);
++	else if (sym_is(symname, "__mod_bcma_device_table"))
++		do_table(symval, sym->st_size,
++			 sizeof(struct bcma_device_id), "bcma",
++			 do_bcma_entry, mod);
+ 	else if (sym_is(symname, "__mod_virtio_device_table"))
+ 		do_table(symval, sym->st_size,
+ 			 sizeof(struct virtio_device_id), "virtio",
diff --git a/target/linux/generic/patches-3.1/020-ssb_update.patch b/target/linux/generic/patches-3.1/020-ssb_update.patch
index 76759273a7..033c5a775b 100644
--- a/target/linux/generic/patches-3.1/020-ssb_update.patch
+++ b/target/linux/generic/patches-3.1/020-ssb_update.patch
@@ -1,14 +1,3 @@
---- a/drivers/ssb/driver_pcicore.c
-+++ b/drivers/ssb/driver_pcicore.c
-@@ -74,7 +74,7 @@ static u32 get_cfgspace_addr(struct ssb_
- 	u32 tmp;
- 
- 	/* We do only have one cardbus device behind the bridge. */
--	if (pc->cardbusmode && (dev >= 1))
-+	if (pc->cardbusmode && (dev > 1))
- 		goto out;
- 
- 	if (bus == 0) {
 --- a/drivers/ssb/b43_pci_bridge.c
 +++ b/drivers/ssb/b43_pci_bridge.c
 @@ -11,6 +11,7 @@
@@ -19,6 +8,15 @@
  #include <linux/ssb/ssb.h>
  
  #include "ssb_private.h"
+@@ -28,6 +29,8 @@ static const struct pci_device_id b43_pc
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4322) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43222) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) },
 --- a/drivers/ssb/driver_chipcommon_pmu.c
 +++ b/drivers/ssb/driver_chipcommon_pmu.c
 @@ -12,6 +12,9 @@
@@ -114,6 +112,17 @@
  	if (bus->extif.dev) {
  		ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m);
  	} else if (bus->chipco.dev) {
+--- a/drivers/ssb/driver_pcicore.c
++++ b/drivers/ssb/driver_pcicore.c
+@@ -74,7 +74,7 @@ static u32 get_cfgspace_addr(struct ssb_
+ 	u32 tmp;
+ 
+ 	/* We do only have one cardbus device behind the bridge. */
+-	if (pc->cardbusmode && (dev >= 1))
++	if (pc->cardbusmode && (dev > 1))
+ 		goto out;
+ 
+ 	if (bus == 0) {
 --- a/drivers/ssb/main.c
 +++ b/drivers/ssb/main.c
 @@ -12,6 +12,7 @@
@@ -216,7 +225,26 @@
  	}
 --- a/drivers/ssb/pci.c
 +++ b/drivers/ssb/pci.c
-@@ -331,7 +331,6 @@ static void sprom_extract_r123(struct ss
+@@ -178,6 +178,18 @@ err_pci:
+ #define SPEX(_outvar, _offset, _mask, _shift) \
+ 	SPEX16(_outvar, _offset, _mask, _shift)
+ 
++#define SPEX_ARRAY8(_field, _offset, _mask, _shift)	\
++	do {	\
++		SPEX(_field[0], _offset +  0, _mask, _shift);	\
++		SPEX(_field[1], _offset +  2, _mask, _shift);	\
++		SPEX(_field[2], _offset +  4, _mask, _shift);	\
++		SPEX(_field[3], _offset +  6, _mask, _shift);	\
++		SPEX(_field[4], _offset +  8, _mask, _shift);	\
++		SPEX(_field[5], _offset + 10, _mask, _shift);	\
++		SPEX(_field[6], _offset + 12, _mask, _shift);	\
++		SPEX(_field[7], _offset + 14, _mask, _shift);	\
++	} while (0)
++
+ 
+ static inline u8 ssb_crc8(u8 crc, u8 data)
+ {
+@@ -331,7 +343,6 @@ static void sprom_extract_r123(struct ss
  {
  	int i;
  	u16 v;
@@ -224,8 +252,24 @@
  	u16 loc[3];
  
  	if (out->revision == 3)			/* rev 3 moved MAC */
-@@ -390,20 +389,12 @@ static void sprom_extract_r123(struct ss
+@@ -361,8 +372,9 @@ static void sprom_extract_r123(struct ss
+ 	SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
+ 	SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
+ 	SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
+-	SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
+-	     SSB_SPROM1_BINF_CCODE_SHIFT);
++	if (out->revision == 1)
++		SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
++		     SSB_SPROM1_BINF_CCODE_SHIFT);
+ 	SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
+ 	     SSB_SPROM1_BINF_ANTA_SHIFT);
+ 	SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
+@@ -388,22 +400,16 @@ static void sprom_extract_r123(struct ss
+ 	SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
+ 	if (out->revision >= 2)
  		SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
++	SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
++	SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
  
  	/* Extract the antenna gain values. */
 -	gain = r123_extract_antgain(out->revision, in,
@@ -251,7 +295,27 @@
  }
  
  /* Revs 4 5 and 8 have partially shared layout */
-@@ -504,16 +495,14 @@ static void sprom_extract_r45(struct ssb
+@@ -464,14 +470,17 @@ static void sprom_extract_r45(struct ssb
+ 	SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
+ 	SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
+ 	     SSB_SPROM4_ETHPHY_ET1A_SHIFT);
++	SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
+ 	if (out->revision == 4) {
+-		SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
++		SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
++		SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
+ 		SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
+ 		SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
+ 		SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
+ 		SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
+ 	} else {
+-		SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0);
++		SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8);
++		SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0);
+ 		SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
+ 		SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
+ 		SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
+@@ -504,16 +513,14 @@ static void sprom_extract_r45(struct ssb
  	}
  
  	/* Extract the antenna gain values. */
@@ -272,7 +336,7 @@
  
  	sprom_extract_r458(out, in);
  
-@@ -523,7 +512,13 @@ static void sprom_extract_r45(struct ssb
+@@ -523,14 +530,22 @@ static void sprom_extract_r45(struct ssb
  static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
  {
  	int i;
@@ -287,7 +351,17 @@
  
  	/* extract the MAC address */
  	for (i = 0; i < 3; i++) {
-@@ -596,16 +591,69 @@ static void sprom_extract_r8(struct ssb_
+ 		v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
+ 		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
+ 	}
+-	SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
++	SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
++	SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
++	SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
+ 	SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
+ 	SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
+ 	SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
+@@ -596,17 +611,127 @@ static void sprom_extract_r8(struct ssb_
  	SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
  
  	/* Extract the antenna gain values. */
@@ -305,7 +379,7 @@
  	     SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
 -	memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
 -	       sizeof(out->antenna_gain.ghz5));
-+
+ 
 +	/* Extract cores power info info */
 +	for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
 +		o = pwr_info_offset[i];
@@ -360,9 +434,75 @@
 +		SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
 +	SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
 +		SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
- 
++
++	SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
++	     SSB_SPROM8_LEDDC_ON_SHIFT);
++	SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
++	     SSB_SPROM8_LEDDC_OFF_SHIFT);
++
++	SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
++	     SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
++	SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
++	     SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
++	SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
++	     SSB_SPROM8_TXRXC_SWITCH_SHIFT);
++
++	SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
++
++	SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
++
++	SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
++	     SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
++	SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
++	     SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
++	SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
++	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
++	SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
++	SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
++	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
++	SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
++	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
++	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
++	SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
++	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
++	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
++	SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
++	     SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
++
++	SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
++	SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
++	SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
++	SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
++
++	SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
++	     SSB_SPROM8_THERMAL_TRESH_SHIFT);
++	SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
++	     SSB_SPROM8_THERMAL_OFFSET_SHIFT);
++	SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
++	     SSB_SPROM8_TEMPDELTA_PHYCAL,
++	     SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
++	SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
++	     SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
++	SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
++	     SSB_SPROM8_TEMPDELTA_HYSTERESIS,
++	     SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
  	sprom_extract_r458(out, in);
  
+ 	/* TODO - get remaining rev 8 stuff needed */
+@@ -736,7 +861,6 @@ static void ssb_pci_get_boardinfo(struct
+ {
+ 	bi->vendor = bus->host_pci->subsystem_vendor;
+ 	bi->type = bus->host_pci->subsystem_device;
+-	bi->rev = bus->host_pci->revision;
+ }
+ 
+ int ssb_pci_get_invariants(struct ssb_bus *bus,
 --- a/drivers/ssb/pcmcia.c
 +++ b/drivers/ssb/pcmcia.c
 @@ -676,14 +676,10 @@ static int ssb_pcmcia_do_get_invariants(
@@ -486,7 +626,7 @@
  	u8 rssisav2g;		/* 2GHz RSSI params */
  	u8 rssismc2g;
  	u8 rssismf2g;
-@@ -82,19 +91,97 @@ struct ssb_sprom {
+@@ -82,26 +91,103 @@ struct ssb_sprom {
  	u16 boardflags2_hi;	/* Board flags (bits 48-63) */
  	/* TODO store board flags in a single u64 */
  
@@ -591,7 +731,14 @@
  };
  
  /* Information about the PCB the circuitry is soldered on. */
-@@ -231,10 +318,9 @@ struct ssb_driver {
+ struct ssb_boardinfo {
+ 	u16 vendor;
+ 	u16 type;
+-	u8  rev;
+ };
+ 
+ 
+@@ -231,10 +317,9 @@ struct ssb_driver {
  #define drv_to_ssb_drv(_drv) container_of(_drv, struct ssb_driver, drv)
  
  extern int __ssb_driver_register(struct ssb_driver *drv, struct module *owner);
@@ -617,8 +764,53 @@
  
 --- a/include/linux/ssb/ssb_regs.h
 +++ b/include/linux/ssb/ssb_regs.h
-@@ -432,6 +432,56 @@
+@@ -228,6 +228,7 @@
+ #define  SSB_SPROM1_AGAIN_BG_SHIFT	0
+ #define  SSB_SPROM1_AGAIN_A		0xFF00	/* A-PHY */
+ #define  SSB_SPROM1_AGAIN_A_SHIFT	8
++#define SSB_SPROM1_CCODE		0x0076
+ 
+ /* SPROM Revision 2 (inherits from rev 1) */
+ #define SSB_SPROM2_BFLHI		0x0038	/* Boardflags (high 16 bits) */
+@@ -267,6 +268,7 @@
+ #define  SSB_SPROM3_OFDMGPO		0x107A	/* G-PHY OFDM Power Offset (4 bytes, BigEndian) */
+ 
+ /* SPROM Revision 4 */
++#define SSB_SPROM4_BOARDREV		0x0042	/* Board revision */
+ #define SSB_SPROM4_BFLLO		0x0044	/* Boardflags (low 16 bits) */
+ #define SSB_SPROM4_BFLHI		0x0046  /* Board Flags Hi */
+ #define SSB_SPROM4_BFL2LO		0x0048	/* Board flags 2 (low 16 bits) */
+@@ -389,6 +391,11 @@
+ #define  SSB_SPROM8_GPIOB_P2		0x00FF	/* Pin 2 */
+ #define  SSB_SPROM8_GPIOB_P3		0xFF00	/* Pin 3 */
+ #define  SSB_SPROM8_GPIOB_P3_SHIFT	8
++#define SSB_SPROM8_LEDDC		0x009A
++#define  SSB_SPROM8_LEDDC_ON		0xFF00	/* oncount */
++#define  SSB_SPROM8_LEDDC_ON_SHIFT	8
++#define  SSB_SPROM8_LEDDC_OFF		0x00FF	/* offcount */
++#define  SSB_SPROM8_LEDDC_OFF_SHIFT	0
+ #define SSB_SPROM8_ANTAVAIL		0x009C  /* Antenna available bitfields*/
+ #define  SSB_SPROM8_ANTAVAIL_A		0xFF00	/* A-PHY bitfield */
+ #define  SSB_SPROM8_ANTAVAIL_A_SHIFT	8
+@@ -404,6 +411,13 @@
+ #define  SSB_SPROM8_AGAIN2_SHIFT	0
+ #define  SSB_SPROM8_AGAIN3		0xFF00	/* Antenna 3 */
+ #define  SSB_SPROM8_AGAIN3_SHIFT	8
++#define SSB_SPROM8_TXRXC		0x00A2
++#define  SSB_SPROM8_TXRXC_TXCHAIN	0x000f
++#define  SSB_SPROM8_TXRXC_TXCHAIN_SHIFT	0
++#define  SSB_SPROM8_TXRXC_RXCHAIN	0x00f0
++#define  SSB_SPROM8_TXRXC_RXCHAIN_SHIFT	4
++#define  SSB_SPROM8_TXRXC_SWITCH	0xff00
++#define  SSB_SPROM8_TXRXC_SWITCH_SHIFT	8
+ #define SSB_SPROM8_RSSIPARM2G		0x00A4	/* RSSI params for 2GHz */
+ #define  SSB_SPROM8_RSSISMF2G		0x000F
+ #define  SSB_SPROM8_RSSISMC2G		0x00F0
+@@ -430,8 +444,87 @@
+ #define  SSB_SPROM8_TRI5GH_SHIFT	8
+ #define SSB_SPROM8_RXPO			0x00AC  /* RX power offsets */
  #define  SSB_SPROM8_RXPO2G		0x00FF	/* 2GHz RX power offset */
++#define  SSB_SPROM8_RXPO2G_SHIFT	0
  #define  SSB_SPROM8_RXPO5G		0xFF00	/* 5GHz RX power offset */
  #define  SSB_SPROM8_RXPO5G_SHIFT	8
 +#define SSB_SPROM8_FEM2G		0x00AE
@@ -634,10 +826,38 @@
 +#define  SSB_SROM8_FEM_ANTSWLUT		0xF800
 +#define  SSB_SROM8_FEM_ANTSWLUT_SHIFT	11
 +#define SSB_SPROM8_THERMAL		0x00B2
-+#define SSB_SPROM8_MPWR_RAWTS		0x00B4
-+#define SSB_SPROM8_TS_SLP_OPT_CORRX	0x00B6
-+#define SSB_SPROM8_FOC_HWIQ_IQSWP	0x00B8
-+#define SSB_SPROM8_PHYCAL_TEMPDELTA	0x00BA
++#define  SSB_SPROM8_THERMAL_OFFSET	0x00ff
++#define  SSB_SPROM8_THERMAL_OFFSET_SHIFT	0
++#define  SSB_SPROM8_THERMAL_TRESH	0xff00
++#define  SSB_SPROM8_THERMAL_TRESH_SHIFT	8
++/* Temp sense related entries */
++#define SSB_SPROM8_RAWTS		0x00B4
++#define  SSB_SPROM8_RAWTS_RAWTEMP	0x01ff
++#define  SSB_SPROM8_RAWTS_RAWTEMP_SHIFT	0
++#define  SSB_SPROM8_RAWTS_MEASPOWER	0xfe00
++#define  SSB_SPROM8_RAWTS_MEASPOWER_SHIFT	9
++#define SSB_SPROM8_OPT_CORRX		0x00B6
++#define  SSB_SPROM8_OPT_CORRX_TEMP_SLOPE	0x00ff
++#define  SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT	0
++#define  SSB_SPROM8_OPT_CORRX_TEMPCORRX	0xfc00
++#define  SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT	10
++#define  SSB_SPROM8_OPT_CORRX_TEMP_OPTION	0x0300
++#define  SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT	8
++/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */
++#define SSB_SPROM8_HWIQ_IQSWP		0x00B8
++#define  SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR	0x000f
++#define  SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT	0
++#define  SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP	0x0010
++#define  SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT	4
++#define  SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL	0x0020
++#define  SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT	5
++#define SSB_SPROM8_TEMPDELTA		0x00BA
++#define  SSB_SPROM8_TEMPDELTA_PHYCAL	0x00ff
++#define  SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT	0
++#define  SSB_SPROM8_TEMPDELTA_PERIOD	0x0f00
++#define  SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT	8
++#define  SSB_SPROM8_TEMPDELTA_HYSTERESIS	0xf000
++#define  SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT	12
 +
 +/* There are 4 blocks with power info sharing the same layout */
 +#define SSB_SROM8_PWR_INFO_CORE0	0x00C0
@@ -674,7 +894,7 @@
  #define SSB_SPROM8_MAXP_BG		0x00C0  /* Max Power 2GHz in path 1 */
  #define  SSB_SPROM8_MAXP_BG_MASK	0x00FF  /* Mask for Max Power 2GHz */
  #define  SSB_SPROM8_ITSSI_BG		0xFF00	/* Mask for path 1 itssi_bg */
-@@ -456,12 +506,53 @@
+@@ -456,12 +549,63 @@
  #define SSB_SPROM8_PA1HIB0		0x00D8	/* 5.8GHz power amp settings */
  #define SSB_SPROM8_PA1HIB1		0x00DA
  #define SSB_SPROM8_PA1HIB2		0x00DC
@@ -685,6 +905,16 @@
  #define SSB_SPROM8_OFDM5GLPO		0x014A	/* 5.2GHz OFDM power offset */
  #define SSB_SPROM8_OFDM5GHPO		0x014E	/* 5.8GHz OFDM power offset */
  
++#define SSB_SPROM8_2G_MCSPO		0x0152
++#define SSB_SPROM8_5G_MCSPO		0x0162
++#define SSB_SPROM8_5GL_MCSPO		0x0172
++#define SSB_SPROM8_5GH_MCSPO		0x0182
++
++#define SSB_SPROM8_CDDPO		0x0192
++#define SSB_SPROM8_STBCPO		0x0194
++#define SSB_SPROM8_BW40PO		0x0196
++#define SSB_SPROM8_BWDUPPO		0x0198
++
 +/* Values for boardflags_lo read from SPROM */
 +#define SSB_BFL_BTCOEXIST		0x0001	/* implements Bluetooth coexistance */
 +#define SSB_BFL_PACTRL			0x0002	/* GPIO 9 controlling the PA */
diff --git a/target/linux/generic/patches-3.1/021-ssb_add_pci_id.patch b/target/linux/generic/patches-3.1/021-ssb_add_pci_id.patch
deleted file mode 100644
index 7cffebec48..0000000000
--- a/target/linux/generic/patches-3.1/021-ssb_add_pci_id.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/drivers/ssb/b43_pci_bridge.c
-+++ b/drivers/ssb/b43_pci_bridge.c
-@@ -29,6 +29,8 @@ static const struct pci_device_id b43_pc
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4322) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43222) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) },
diff --git a/target/linux/generic/patches-3.1/025-bcma_backport.patch b/target/linux/generic/patches-3.1/025-bcma_backport.patch
index 1f0b9b5126..c75896f0ad 100644
--- a/target/linux/generic/patches-3.1/025-bcma_backport.patch
+++ b/target/linux/generic/patches-3.1/025-bcma_backport.patch
@@ -91,7 +91,24 @@
  #endif
 --- a/drivers/bcma/core.c
 +++ b/drivers/bcma/core.c
-@@ -110,6 +110,8 @@ EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
+@@ -29,6 +29,7 @@ void bcma_core_disable(struct bcma_devic
+ 	udelay(10);
+ 
+ 	bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
++	bcma_aread32(core, BCMA_RESET_CTL);
+ 	udelay(1);
+ }
+ EXPORT_SYMBOL_GPL(bcma_core_disable);
+@@ -76,7 +77,7 @@ void bcma_core_set_clockmode(struct bcma
+ 			pr_err("HT force timeout\n");
+ 		break;
+ 	case BCMA_CLKMODE_DYNAMIC:
+-		pr_warn("Dynamic clockmode not supported yet!\n");
++		bcma_set32(core, BCMA_CLKCTLST, ~BCMA_CLKCTLST_FORCEHT);
+ 		break;
+ 	}
+ }
+@@ -110,6 +111,8 @@ EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
  u32 bcma_core_dma_translation(struct bcma_device *core)
  {
  	switch (core->bus->hosttype) {
@@ -676,7 +693,7 @@
   *
   * Licensed under the GNU/GPL. See COPYING for details.
   */
-@@ -15,40 +16,41 @@
+@@ -15,40 +16,39 @@
   * R/W ops.
   **************************************************/
  
@@ -691,7 +708,7 @@
 +	return pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_DATA);
  }
  
- #if 0
+-#if 0
  static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data)
  {
 -	pcicore_write32(pc, 0x130, address);
@@ -701,7 +718,7 @@
 +	pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR);
 +	pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_DATA, data);
  }
- #endif
+-#endif
  
  static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy)
  {
@@ -734,7 +751,7 @@
  			break;
  		msleep(1);
  	}
-@@ -56,79 +58,84 @@ static void bcma_pcie_mdio_set_phy(struc
+@@ -56,79 +56,84 @@ static void bcma_pcie_mdio_set_phy(struc
  
  static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address)
  {
@@ -850,7 +867,7 @@
  }
  
  /**************************************************
-@@ -137,67 +144,53 @@ static void bcma_pcie_mdio_write(struct
+@@ -137,67 +142,90 @@ static void bcma_pcie_mdio_write(struct
  
  static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc)
  {
@@ -885,6 +902,41 @@
 +		bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL,
 +		                     BCMA_CORE_PCI_SERDES_PLL_CTRL,
 +		                     tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN);
++}
++
++static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc)
++{
++	struct bcma_device *core = pc->core;
++	u16 val16, core_index;
++	uint regoff;
++
++	regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_PI_OFFSET);
++	core_index = (u16)core->core_index;
++
++	val16 = pcicore_read16(pc, regoff);
++	if (((val16 & BCMA_CORE_PCI_SPROM_PI_MASK) >> BCMA_CORE_PCI_SPROM_PI_SHIFT)
++	     != core_index) {
++		val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) |
++			(val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK);
++		pcicore_write16(pc, regoff, val16);
++	}
++}
++
++/* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */
++/* Needs to happen when coming out of 'standby'/'hibernate' */
++static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc)
++{
++	u16 val16;
++	uint regoff;
++
++	regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_MISC_CONFIG);
++
++	val16 = pcicore_read16(pc, regoff);
++
++	if (!(val16 & BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST)) {
++		val16 |= BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST;
++		pcicore_write16(pc, regoff, val16);
++	}
  }
  
  /**************************************************
@@ -894,7 +946,9 @@
 -static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
 +static void __devinit bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
  {
++	bcma_core_pci_fixcfg(pc);
  	bcma_pcicore_serdes_workaround(pc);
++	bcma_core_pci_config_fixup(pc);
  }
  
 -static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
@@ -902,7 +956,9 @@
  {
 -	struct bcma_bus *bus = pc->core->bus;
 -	u16 chipid_top;
--
++	if (pc->setup_done)
++		return;
+ 
 -	chipid_top = (bus->chipinfo.id & 0xFF00);
 -	if (chipid_top != 0x4700 &&
 -	    chipid_top != 0x5300)
@@ -922,9 +978,7 @@
 -
 -	return true;
 -}
-+	if (pc->setup_done)
-+		return;
- 
+-
 -void bcma_core_pci_init(struct bcma_drv_pci *pc)
 -{
 -	if (bcma_core_pci_is_in_hostmode(pc)) {
@@ -943,7 +997,7 @@
  }
  
  int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
-@@ -205,7 +198,14 @@ int bcma_core_pci_irq_ctl(struct bcma_dr
+@@ -205,7 +233,14 @@ int bcma_core_pci_irq_ctl(struct bcma_dr
  {
  	struct pci_dev *pdev = pc->core->bus->host_pci;
  	u32 coremask, tmp;
@@ -959,6 +1013,24 @@
  
  	err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
  	if (err)
+@@ -223,3 +258,17 @@ out:
+ 	return err;
+ }
+ EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
++
++void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend)
++{
++	u32 w;
++
++	w = bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG);
++	if (extend)
++		w |= BCMA_CORE_PCI_ASPMTIMER_EXTEND;
++	else
++		w &= ~BCMA_CORE_PCI_ASPMTIMER_EXTEND;
++	bcma_pcie_write(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG, w);
++	bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG);
++}
++EXPORT_SYMBOL_GPL(bcma_core_pci_extend_L1timer);
 --- a/drivers/bcma/driver_pci_host.c
 +++ b/drivers/bcma/driver_pci_host.c
 @@ -2,13 +2,587 @@
@@ -1083,7 +1155,7 @@
 +		if (unlikely(!addr))
 +			goto out;
 +		err = -ENOMEM;
-+		mmio = ioremap_nocache(addr, len);
++		mmio = ioremap_nocache(addr, sizeof(val));
 +		if (!mmio)
 +			goto out;
 +
@@ -1135,7 +1207,7 @@
 +			addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0;
 +			addr |= (func << 8);
 +			addr |= (off & 0xfc);
-+			mmio = ioremap_nocache(addr, len);
++			mmio = ioremap_nocache(addr, sizeof(val));
 +			if (!mmio)
 +				goto out;
 +		}
@@ -1144,7 +1216,7 @@
 +		if (unlikely(!addr))
 +			goto out;
 +		err = -ENOMEM;
-+		mmio = ioremap_nocache(addr, len);
++		mmio = ioremap_nocache(addr, sizeof(val));
 +		if (!mmio)
 +			goto out;
 +
@@ -1455,8 +1527,8 @@
 +	/* Ok, ready to run, register it to the system.
 +	 * The following needs change, if we want to port hostmode
 +	 * to non-MIPS platform. */
-+	io_map_base = (unsigned long)ioremap_nocache(BCMA_SOC_PCI_MEM,
-+						     0x04000000);
++	io_map_base = (unsigned long)ioremap_nocache(pc_host->mem_resource.start,
++						     resource_size(&pc_host->mem_resource));
 +	pc_host->pci_controller.io_map_base = io_map_base;
 +	set_io_port_base(pc_host->pci_controller.io_map_base);
 +	/* Give some time to the PCI controller to configure itself with the new
@@ -1643,7 +1715,26 @@
  {
  	struct bcma_bus *bus;
  	int err = -ENOMEM;
-@@ -223,6 +234,35 @@ static void bcma_host_pci_remove(struct
+@@ -190,6 +201,9 @@ static int bcma_host_pci_probe(struct pc
+ 	bus->hosttype = BCMA_HOSTTYPE_PCI;
+ 	bus->ops = &bcma_host_pci_ops;
+ 
++	bus->boardinfo.vendor = bus->host_pci->subsystem_vendor;
++	bus->boardinfo.type = bus->host_pci->subsystem_device;
++
+ 	/* Register */
+ 	err = bcma_bus_register(bus);
+ 	if (err)
+@@ -211,7 +225,7 @@ err_kfree_bus:
+ 	return err;
+ }
+ 
+-static void bcma_host_pci_remove(struct pci_dev *dev)
++static void __devexit bcma_host_pci_remove(struct pci_dev *dev)
+ {
+ 	struct bcma_bus *bus = pci_get_drvdata(dev);
+ 
+@@ -223,6 +237,35 @@ static void bcma_host_pci_remove(struct
  	pci_set_drvdata(dev, NULL);
  }
  
@@ -1679,10 +1770,12 @@
  static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
  	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
  	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
-@@ -238,6 +278,7 @@ static struct pci_driver bcma_pci_bridge
+@@ -237,7 +280,8 @@ static struct pci_driver bcma_pci_bridge
+ 	.name = "bcma-pci-bridge",
  	.id_table = bcma_pci_bridge_tbl,
  	.probe = bcma_host_pci_probe,
- 	.remove = bcma_host_pci_remove,
+-	.remove = bcma_host_pci_remove,
++	.remove = __devexit_p(bcma_host_pci_remove),
 +	.driver.pm = BCMA_PM_OPS,
  };
  
@@ -2092,7 +2185,104 @@
  	drv->drv.name = drv->name;
 --- a/drivers/bcma/scan.c
 +++ b/drivers/bcma/scan.c
-@@ -200,18 +200,174 @@ static s32 bcma_erom_get_addr_desc(struc
+@@ -19,7 +19,14 @@ struct bcma_device_id_name {
+ 	u16 id;
+ 	const char *name;
+ };
+-struct bcma_device_id_name bcma_device_names[] = {
++
++static const struct bcma_device_id_name bcma_arm_device_names[] = {
++	{ BCMA_CORE_ARM_1176, "ARM 1176" },
++	{ BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },
++	{ BCMA_CORE_ARM_CM3, "ARM CM3" },
++};
++
++static const struct bcma_device_id_name bcma_bcm_device_names[] = {
+ 	{ BCMA_CORE_OOB_ROUTER, "OOB Router" },
+ 	{ BCMA_CORE_INVALID, "Invalid" },
+ 	{ BCMA_CORE_CHIPCOMMON, "ChipCommon" },
+@@ -27,7 +34,6 @@ struct bcma_device_id_name bcma_device_n
+ 	{ BCMA_CORE_SRAM, "SRAM" },
+ 	{ BCMA_CORE_SDRAM, "SDRAM" },
+ 	{ BCMA_CORE_PCI, "PCI" },
+-	{ BCMA_CORE_MIPS, "MIPS" },
+ 	{ BCMA_CORE_ETHERNET, "Fast Ethernet" },
+ 	{ BCMA_CORE_V90, "V90" },
+ 	{ BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" },
+@@ -44,7 +50,6 @@ struct bcma_device_id_name bcma_device_n
+ 	{ BCMA_CORE_PHY_A, "PHY A" },
+ 	{ BCMA_CORE_PHY_B, "PHY B" },
+ 	{ BCMA_CORE_PHY_G, "PHY G" },
+-	{ BCMA_CORE_MIPS_3302, "MIPS 3302" },
+ 	{ BCMA_CORE_USB11_HOST, "USB 1.1 Host" },
+ 	{ BCMA_CORE_USB11_DEV, "USB 1.1 Device" },
+ 	{ BCMA_CORE_USB20_HOST, "USB 2.0 Host" },
+@@ -58,15 +63,11 @@ struct bcma_device_id_name bcma_device_n
+ 	{ BCMA_CORE_PHY_N, "PHY N" },
+ 	{ BCMA_CORE_SRAM_CTL, "SRAM Controller" },
+ 	{ BCMA_CORE_MINI_MACPHY, "Mini MACPHY" },
+-	{ BCMA_CORE_ARM_1176, "ARM 1176" },
+-	{ BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },
+ 	{ BCMA_CORE_PHY_LP, "PHY LP" },
+ 	{ BCMA_CORE_PMU, "PMU" },
+ 	{ BCMA_CORE_PHY_SSN, "PHY SSN" },
+ 	{ BCMA_CORE_SDIO_DEV, "SDIO Device" },
+-	{ BCMA_CORE_ARM_CM3, "ARM CM3" },
+ 	{ BCMA_CORE_PHY_HT, "PHY HT" },
+-	{ BCMA_CORE_MIPS_74K, "MIPS 74K" },
+ 	{ BCMA_CORE_MAC_GBIT, "GBit MAC" },
+ 	{ BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" },
+ 	{ BCMA_CORE_PCIE_RC, "PCIe Root Complex" },
+@@ -79,16 +80,41 @@ struct bcma_device_id_name bcma_device_n
+ 	{ BCMA_CORE_SHIM, "SHIM" },
+ 	{ BCMA_CORE_DEFAULT, "Default" },
+ };
+-const char *bcma_device_name(struct bcma_device_id *id)
++
++static const struct bcma_device_id_name bcma_mips_device_names[] = {
++	{ BCMA_CORE_MIPS, "MIPS" },
++	{ BCMA_CORE_MIPS_3302, "MIPS 3302" },
++	{ BCMA_CORE_MIPS_74K, "MIPS 74K" },
++};
++
++static const char *bcma_device_name(const struct bcma_device_id *id)
+ {
+-	int i;
++	const struct bcma_device_id_name *names;
++	int size, i;
+ 
+-	if (id->manuf == BCMA_MANUF_BCM) {
+-		for (i = 0; i < ARRAY_SIZE(bcma_device_names); i++) {
+-			if (bcma_device_names[i].id == id->id)
+-				return bcma_device_names[i].name;
+-		}
++	/* search manufacturer specific names */
++	switch (id->manuf) {
++	case BCMA_MANUF_ARM:
++		names = bcma_arm_device_names;
++		size = ARRAY_SIZE(bcma_arm_device_names);
++		break;
++	case BCMA_MANUF_BCM:
++		names = bcma_bcm_device_names;
++		size = ARRAY_SIZE(bcma_bcm_device_names);
++		break;
++	case BCMA_MANUF_MIPS:
++		names = bcma_mips_device_names;
++		size = ARRAY_SIZE(bcma_mips_device_names);
++		break;
++	default:
++		return "UNKNOWN";
++	}
++
++	for (i = 0; i < size; i++) {
++		if (names[i].id == id->id)
++			return names[i].name;
+ 	}
++
+ 	return "UNKNOWN";
+ }
+ 
+@@ -200,18 +226,174 @@ static s32 bcma_erom_get_addr_desc(struc
  	return addrl;
  }
  
@@ -2272,7 +2462,7 @@
  
  	INIT_LIST_HEAD(&bus->cores);
  	bus->nr_cores = 0;
-@@ -219,142 +375,133 @@ int bcma_bus_scan(struct bcma_bus *bus)
+@@ -219,142 +401,133 @@ int bcma_bus_scan(struct bcma_bus *bus)
  	bcma_scan_switch_core(bus, BCMA_ADDR_BASE);
  
  	tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID);
@@ -2468,7 +2658,7 @@
 +	} else {
 +		eromptr = bus->mmio;
 +	}
- 
++
 +	eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
 +
 +	bcma_scan_switch_core(bus, erombase);
@@ -2488,7 +2678,7 @@
 +			break;
 +		else if (err < 0)
 +			return err;
-+
+ 
 +		core->core_index = core_num++;
 +		bus->nr_cores++;
  		pr_info("Core %d found: %s "
@@ -2583,7 +2773,7 @@
  
  /**************************************************
   * R/W ops.
-@@ -124,41 +176,268 @@ static int bcma_sprom_valid(const u16 *s
+@@ -124,41 +176,418 @@ static int bcma_sprom_valid(const u16 *s
   * SPROM extraction.
   **************************************************/
  
@@ -2591,6 +2781,22 @@
 +
 +#define SPEX(_field, _offset, _mask, _shift)	\
 +	bus->sprom._field = ((sprom[SPOFF(_offset)] & (_mask)) >> (_shift))
++
++#define SPEX32(_field, _offset, _mask, _shift)	\
++	bus->sprom._field = ((((u32)sprom[SPOFF((_offset)+2)] << 16 | \
++				sprom[SPOFF(_offset)]) & (_mask)) >> (_shift))
++
++#define SPEX_ARRAY8(_field, _offset, _mask, _shift)	\
++	do {	\
++		SPEX(_field[0], _offset +  0, _mask, _shift);	\
++		SPEX(_field[1], _offset +  2, _mask, _shift);	\
++		SPEX(_field[2], _offset +  4, _mask, _shift);	\
++		SPEX(_field[3], _offset +  6, _mask, _shift);	\
++		SPEX(_field[4], _offset +  8, _mask, _shift);	\
++		SPEX(_field[5], _offset + 10, _mask, _shift);	\
++		SPEX(_field[6], _offset + 12, _mask, _shift);	\
++		SPEX(_field[7], _offset + 14, _mask, _shift);	\
++	} while (0)
 +
  static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
  {
@@ -2655,7 +2861,8 @@
 +	SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, ~0, 0);
 +	SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, ~0, 0);
 +
-+	SPEX(country_code, SSB_SPROM8_CCODE, ~0, 0);
++	SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
++	SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
 +
 +	/* Extract cores power info info */
 +	for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
@@ -2710,6 +2917,136 @@
 +	     SSB_SROM8_FEM_TR_ISO_SHIFT);
 +	SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT,
 +	     SSB_SROM8_FEM_ANTSWLUT_SHIFT);
++
++	SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
++	     SSB_SPROM8_ANTAVAIL_A_SHIFT);
++	SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
++	     SSB_SPROM8_ANTAVAIL_BG_SHIFT);
++	SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
++	SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
++	     SSB_SPROM8_ITSSI_BG_SHIFT);
++	SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
++	SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
++	     SSB_SPROM8_ITSSI_A_SHIFT);
++	SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
++	SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
++	     SSB_SPROM8_MAXP_AL_SHIFT);
++	SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
++	SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
++	     SSB_SPROM8_GPIOA_P1_SHIFT);
++	SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
++	SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
++	     SSB_SPROM8_GPIOB_P3_SHIFT);
++	SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
++	SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
++	     SSB_SPROM8_TRI5G_SHIFT);
++	SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
++	SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
++	     SSB_SPROM8_TRI5GH_SHIFT);
++	SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G,
++	     SSB_SPROM8_RXPO2G_SHIFT);
++	SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
++	     SSB_SPROM8_RXPO5G_SHIFT);
++	SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
++	SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
++	     SSB_SPROM8_RSSISMC2G_SHIFT);
++	SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
++	     SSB_SPROM8_RSSISAV2G_SHIFT);
++	SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
++	     SSB_SPROM8_BXA2G_SHIFT);
++	SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
++	SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
++	     SSB_SPROM8_RSSISMC5G_SHIFT);
++	SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
++	     SSB_SPROM8_RSSISAV5G_SHIFT);
++	SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
++	     SSB_SPROM8_BXA5G_SHIFT);
++
++	SPEX(pa0b0, SSB_SPROM8_PA0B0, ~0, 0);
++	SPEX(pa0b1, SSB_SPROM8_PA0B1, ~0, 0);
++	SPEX(pa0b2, SSB_SPROM8_PA0B2, ~0, 0);
++	SPEX(pa1b0, SSB_SPROM8_PA1B0, ~0, 0);
++	SPEX(pa1b1, SSB_SPROM8_PA1B1, ~0, 0);
++	SPEX(pa1b2, SSB_SPROM8_PA1B2, ~0, 0);
++	SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, ~0, 0);
++	SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, ~0, 0);
++	SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, ~0, 0);
++	SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, ~0, 0);
++	SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, ~0, 0);
++	SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, ~0, 0);
++	SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, ~0, 0);
++	SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, ~0, 0);
++	SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, ~0, 0);
++	SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, ~0, 0);
++	SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0);
++
++	/* Extract the antenna gain values. */
++	SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
++	     SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
++	SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
++	     SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
++	SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
++	     SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
++	SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
++	     SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
++
++	SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
++	     SSB_SPROM8_LEDDC_ON_SHIFT);
++	SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
++	     SSB_SPROM8_LEDDC_OFF_SHIFT);
++
++	SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
++	     SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
++	SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
++	     SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
++	SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
++	     SSB_SPROM8_TXRXC_SWITCH_SHIFT);
++
++	SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
++
++	SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
++
++	SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
++	     SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
++	SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
++	     SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
++	SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
++	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
++	SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
++	SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
++	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
++	SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
++	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
++	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
++	SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
++	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
++	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
++	SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
++	     SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
++
++	SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
++	SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
++	SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
++	SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
++
++	SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
++	     SSB_SPROM8_THERMAL_TRESH_SHIFT);
++	SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
++	     SSB_SPROM8_THERMAL_OFFSET_SHIFT);
++	SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
++	     SSB_SPROM8_TEMPDELTA_PHYCAL,
++	     SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
++	SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
++	     SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
++	SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
++	     SSB_SPROM8_TEMPDELTA_HYSTERESIS,
++	     SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
 +}
 +
 +/*
@@ -2819,16 +3156,19 @@
 -	if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
 -		return -ENOENT;
 +	if (!bcma_sprom_ext_available(bus)) {
++		bool sprom_onchip;
++
 +		/*
 +		 * External SPROM takes precedence so check
 +		 * on-chip OTP only when no external SPROM
 +		 * is present.
 +		 */
-+		if (bcma_sprom_onchip_available(bus)) {
++		sprom_onchip = bcma_sprom_onchip_available(bus);
++		if (sprom_onchip) {
 +			/* determine offset */
 +			offset = bcma_sprom_onchip_offset(bus);
 +		}
-+		if (!offset) {
++		if (!offset || !sprom_onchip) {
 +			/*
 +			 * Maybe there is no SPROM on the device?
 +			 * Now we ask the arch code if there is some sprom
@@ -2882,7 +3222,19 @@
  };
  
  struct bcma_chipinfo {
-@@ -130,14 +131,19 @@ struct bcma_device {
+@@ -25,6 +26,11 @@ struct bcma_chipinfo {
+ 	u8 pkg;
+ };
+ 
++struct bcma_boardinfo {
++	u16 vendor;
++	u16 type;
++};
++
+ enum bcma_clkmode {
+ 	BCMA_CLKMODE_FAST,
+ 	BCMA_CLKMODE_DYNAMIC,
+@@ -130,14 +136,19 @@ struct bcma_device {
  
  	struct device dev;
  	struct device *dma_dev;
@@ -2902,7 +3254,7 @@
  	void *drvdata;
  	struct list_head list;
  };
-@@ -157,7 +163,7 @@ struct bcma_driver {
+@@ -157,7 +168,7 @@ struct bcma_driver {
  
  	int (*probe)(struct bcma_device *dev);
  	void (*remove)(struct bcma_device *dev);
@@ -2911,7 +3263,7 @@
  	int (*resume)(struct bcma_device *dev);
  	void (*shutdown)(struct bcma_device *dev);
  
-@@ -165,12 +171,17 @@ struct bcma_driver {
+@@ -165,12 +176,17 @@ struct bcma_driver {
  };
  extern
  int __bcma_driver_register(struct bcma_driver *drv, struct module *owner);
@@ -2933,7 +3285,12 @@
  struct bcma_bus {
  	/* The MMIO area. */
  	void __iomem *mmio;
-@@ -190,71 +201,96 @@ struct bcma_bus {
+@@ -187,74 +203,101 @@ struct bcma_bus {
+ 
+ 	struct bcma_chipinfo chipinfo;
+ 
++	struct bcma_boardinfo boardinfo;
++
  	struct bcma_device *mapped_core;
  	struct list_head cores;
  	u8 nr_cores;
@@ -3303,7 +3660,7 @@
 +#endif /* LINUX_BCMA_DRIVER_MIPS_H_ */
 --- a/include/linux/bcma/bcma_driver_pci.h
 +++ b/include/linux/bcma/bcma_driver_pci.h
-@@ -53,6 +53,35 @@ struct pci_dev;
+@@ -53,11 +53,47 @@ struct pci_dev;
  #define  BCMA_CORE_PCI_SBTOPCI1_MASK		0xFC000000
  #define BCMA_CORE_PCI_SBTOPCI2			0x0108	/* Backplane to PCI translation 2 (sbtopci2) */
  #define  BCMA_CORE_PCI_SBTOPCI2_MASK		0xC0000000
@@ -3339,7 +3696,19 @@
  #define BCMA_CORE_PCI_PCICFG0			0x0400	/* PCI config space 0 (rev >= 8) */
  #define BCMA_CORE_PCI_PCICFG1			0x0500	/* PCI config space 1 (rev >= 8) */
  #define BCMA_CORE_PCI_PCICFG2			0x0600	/* PCI config space 2 (rev >= 8) */
-@@ -72,20 +101,114 @@ struct pci_dev;
+ #define BCMA_CORE_PCI_PCICFG3			0x0700	/* PCI config space 3 (rev >= 8) */
+ #define BCMA_CORE_PCI_SPROM(wordoffset)		(0x0800 + ((wordoffset) * 2)) /* SPROM shadow area (72 bytes) */
++#define  BCMA_CORE_PCI_SPROM_PI_OFFSET		0	/* first word */
++#define   BCMA_CORE_PCI_SPROM_PI_MASK		0xf000	/* bit 15:12 */
++#define   BCMA_CORE_PCI_SPROM_PI_SHIFT		12	/* bit 15:12 */
++#define  BCMA_CORE_PCI_SPROM_MISC_CONFIG	5	/* word 5 */
++#define   BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST	0x8000	/* bit 15 */
++#define   BCMA_CORE_PCI_SPROM_CLKREQ_OFFSET_REV5	20	/* word 20 for srom rev <= 5 */
++#define   BCMA_CORE_PCI_SPROM_CLKREQ_ENB	0x0800	/* bit 11 */
+ 
+ /* SBtoPCIx */
+ #define BCMA_CORE_PCI_SBTOPCI_MEM		0x00000000
+@@ -72,20 +108,118 @@ struct pci_dev;
  #define  BCMA_CORE_PCI_SBTOPCI_RC_READL		0x00000010 /* Memory read line */
  #define  BCMA_CORE_PCI_SBTOPCI_RC_READM		0x00000020 /* Memory read multiple */
  
@@ -3375,6 +3744,7 @@
 +#define BCMA_CORE_PCI_DLLP_LRREG		0x120	/* Link Replay */
 +#define BCMA_CORE_PCI_DLLP_LACKTOREG		0x124	/* Link Ack Timeout */
 +#define BCMA_CORE_PCI_DLLP_PMTHRESHREG		0x128	/* Power Management Threshold */
++#define  BCMA_CORE_PCI_ASPMTIMER_EXTEND		0x01000000 /* > rev7: enable extend ASPM timer */
 +#define BCMA_CORE_PCI_DLLP_RTRYWPREG		0x12C	/* Retry buffer write ptr */
 +#define BCMA_CORE_PCI_DLLP_RTRYRPREG		0x130	/* Retry buffer Read ptr */
 +#define BCMA_CORE_PCI_DLLP_RTRYPPREG		0x134	/* Retry buffer Purged ptr */
@@ -3443,17 +3813,20 @@
  };
  
  /* Register access */
++#define pcicore_read16(pc, offset)		bcma_read16((pc)->core, offset)
  #define pcicore_read32(pc, offset)		bcma_read32((pc)->core, offset)
++#define pcicore_write16(pc, offset, val)	bcma_write16((pc)->core, offset, val)
  #define pcicore_write32(pc, offset, val)	bcma_write32((pc)->core, offset, val)
  
 -extern void bcma_core_pci_init(struct bcma_drv_pci *pc);
 +extern void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc);
  extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
  				 struct bcma_device *core, bool enable);
- 
++extern void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend);
++
 +extern int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev);
 +extern int bcma_core_pci_plat_dev_init(struct pci_dev *dev);
-+
+ 
  #endif /* LINUX_BCMA_DRIVER_PCI_H_ */
 --- a/include/linux/bcma/bcma_regs.h
 +++ b/include/linux/bcma/bcma_regs.h
diff --git a/target/linux/generic/patches-3.2/020-ssb_update.patch b/target/linux/generic/patches-3.2/020-ssb_update.patch
index 1b38e380d4..0aabe57a31 100644
--- a/target/linux/generic/patches-3.2/020-ssb_update.patch
+++ b/target/linux/generic/patches-3.2/020-ssb_update.patch
@@ -1,3 +1,14 @@
+--- a/drivers/ssb/b43_pci_bridge.c
++++ b/drivers/ssb/b43_pci_bridge.c
+@@ -29,6 +29,8 @@ static const struct pci_device_id b43_pc
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4322) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43222) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) },
 --- a/drivers/ssb/driver_chipcommon_pmu.c
 +++ b/drivers/ssb/driver_chipcommon_pmu.c
 @@ -13,6 +13,9 @@
@@ -160,7 +171,26 @@
  					   &clkctl_n, &clkctl_m);
 --- a/drivers/ssb/pci.c
 +++ b/drivers/ssb/pci.c
-@@ -331,7 +331,6 @@ static void sprom_extract_r123(struct ss
+@@ -178,6 +178,18 @@ err_pci:
+ #define SPEX(_outvar, _offset, _mask, _shift) \
+ 	SPEX16(_outvar, _offset, _mask, _shift)
+ 
++#define SPEX_ARRAY8(_field, _offset, _mask, _shift)	\
++	do {	\
++		SPEX(_field[0], _offset +  0, _mask, _shift);	\
++		SPEX(_field[1], _offset +  2, _mask, _shift);	\
++		SPEX(_field[2], _offset +  4, _mask, _shift);	\
++		SPEX(_field[3], _offset +  6, _mask, _shift);	\
++		SPEX(_field[4], _offset +  8, _mask, _shift);	\
++		SPEX(_field[5], _offset + 10, _mask, _shift);	\
++		SPEX(_field[6], _offset + 12, _mask, _shift);	\
++		SPEX(_field[7], _offset + 14, _mask, _shift);	\
++	} while (0)
++
+ 
+ static inline u8 ssb_crc8(u8 crc, u8 data)
+ {
+@@ -331,7 +343,6 @@ static void sprom_extract_r123(struct ss
  {
  	int i;
  	u16 v;
@@ -168,8 +198,24 @@
  	u16 loc[3];
  
  	if (out->revision == 3)			/* rev 3 moved MAC */
-@@ -390,20 +389,12 @@ static void sprom_extract_r123(struct ss
+@@ -361,8 +372,9 @@ static void sprom_extract_r123(struct ss
+ 	SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
+ 	SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
+ 	SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
+-	SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
+-	     SSB_SPROM1_BINF_CCODE_SHIFT);
++	if (out->revision == 1)
++		SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
++		     SSB_SPROM1_BINF_CCODE_SHIFT);
+ 	SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
+ 	     SSB_SPROM1_BINF_ANTA_SHIFT);
+ 	SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
+@@ -388,22 +400,16 @@ static void sprom_extract_r123(struct ss
+ 	SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
+ 	if (out->revision >= 2)
  		SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
++	SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
++	SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
  
  	/* Extract the antenna gain values. */
 -	gain = r123_extract_antgain(out->revision, in,
@@ -195,7 +241,27 @@
  }
  
  /* Revs 4 5 and 8 have partially shared layout */
-@@ -504,16 +495,14 @@ static void sprom_extract_r45(struct ssb
+@@ -464,14 +470,17 @@ static void sprom_extract_r45(struct ssb
+ 	SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
+ 	SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
+ 	     SSB_SPROM4_ETHPHY_ET1A_SHIFT);
++	SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
+ 	if (out->revision == 4) {
+-		SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
++		SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
++		SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
+ 		SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
+ 		SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
+ 		SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
+ 		SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
+ 	} else {
+-		SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0);
++		SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8);
++		SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0);
+ 		SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
+ 		SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
+ 		SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
+@@ -504,16 +513,14 @@ static void sprom_extract_r45(struct ssb
  	}
  
  	/* Extract the antenna gain values. */
@@ -216,7 +282,7 @@
  
  	sprom_extract_r458(out, in);
  
-@@ -523,7 +512,13 @@ static void sprom_extract_r45(struct ssb
+@@ -523,14 +530,22 @@ static void sprom_extract_r45(struct ssb
  static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
  {
  	int i;
@@ -231,7 +297,17 @@
  
  	/* extract the MAC address */
  	for (i = 0; i < 3; i++) {
-@@ -596,16 +591,69 @@ static void sprom_extract_r8(struct ssb_
+ 		v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
+ 		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
+ 	}
+-	SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
++	SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
++	SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
++	SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
+ 	SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
+ 	SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
+ 	SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
+@@ -596,17 +611,127 @@ static void sprom_extract_r8(struct ssb_
  	SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
  
  	/* Extract the antenna gain values. */
@@ -249,7 +325,7 @@
  	     SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
 -	memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
 -	       sizeof(out->antenna_gain.ghz5));
-+
+ 
 +	/* Extract cores power info info */
 +	for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
 +		o = pwr_info_offset[i];
@@ -304,9 +380,75 @@
 +		SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
 +	SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
 +		SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
- 
++
++	SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
++	     SSB_SPROM8_LEDDC_ON_SHIFT);
++	SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
++	     SSB_SPROM8_LEDDC_OFF_SHIFT);
++
++	SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
++	     SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
++	SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
++	     SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
++	SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
++	     SSB_SPROM8_TXRXC_SWITCH_SHIFT);
++
++	SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
++
++	SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
++
++	SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
++	     SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
++	SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
++	     SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
++	SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
++	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
++	SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
++	SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
++	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
++	SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
++	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
++	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
++	SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
++	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
++	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
++	SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
++	     SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
++
++	SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
++	SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
++	SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
++	SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
++
++	SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
++	     SSB_SPROM8_THERMAL_TRESH_SHIFT);
++	SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
++	     SSB_SPROM8_THERMAL_OFFSET_SHIFT);
++	SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
++	     SSB_SPROM8_TEMPDELTA_PHYCAL,
++	     SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
++	SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
++	     SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
++	SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
++	     SSB_SPROM8_TEMPDELTA_HYSTERESIS,
++	     SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
  	sprom_extract_r458(out, in);
  
+ 	/* TODO - get remaining rev 8 stuff needed */
+@@ -736,7 +861,6 @@ static void ssb_pci_get_boardinfo(struct
+ {
+ 	bi->vendor = bus->host_pci->subsystem_vendor;
+ 	bi->type = bus->host_pci->subsystem_device;
+-	bi->rev = bus->host_pci->revision;
+ }
+ 
+ int ssb_pci_get_invariants(struct ssb_bus *bus,
 --- a/drivers/ssb/pcmcia.c
 +++ b/drivers/ssb/pcmcia.c
 @@ -676,14 +676,10 @@ static int ssb_pcmcia_do_get_invariants(
@@ -428,7 +570,7 @@
  	u8 rssisav2g;		/* 2GHz RSSI params */
  	u8 rssismc2g;
  	u8 rssismf2g;
-@@ -82,19 +91,97 @@ struct ssb_sprom {
+@@ -82,26 +91,103 @@ struct ssb_sprom {
  	u16 boardflags2_hi;	/* Board flags (bits 48-63) */
  	/* TODO store board flags in a single u64 */
  
@@ -438,19 +580,21 @@
  	 * on each band. Values in dBm/4 (Q5.2). Negative gain means the
  	 * loss in the connectors is bigger than the gain. */
  	struct {
-+		s8 a0, a1, a2, a3;
-+	} antenna_gain;
-+
-+	struct {
- 		struct {
+-		struct {
 -			s8 a0, a1, a2, a3;
 -		} ghz24;	/* 2.4GHz band */
-+			u8 tssipos, extpa_gain, pdet_range, tr_iso, antswlut;
-+		} ghz2;
- 		struct {
+-		struct {
 -			s8 a0, a1, a2, a3;
 -		} ghz5;		/* 5GHz band */
--	} antenna_gain;
++		s8 a0, a1, a2, a3;
+ 	} antenna_gain;
+ 
+-	/* TODO - add any parameters needed from rev 2, 3, 4, 5 or 8 SPROMs */
++	struct {
++		struct {
++			u8 tssipos, extpa_gain, pdet_range, tr_iso, antswlut;
++		} ghz2;
++		struct {
 +			u8 tssipos, extpa_gain, pdet_range, tr_iso, antswlut;
 +		} ghz5;
 +	} fem;
@@ -500,8 +644,7 @@
 +	u8 measpower1;
 +	u8 measpower2;
 +	u8 pcieingress_war;
- 
--	/* TODO - add any parameters needed from rev 2, 3, 4, 5 or 8 SPROMs */
++
 +	/* power per rate from sromrev 9 */
 +	u16 cckbw202gpo;
 +	u16 cckbw20ul2gpo;
@@ -532,6 +675,13 @@
  };
  
  /* Information about the PCB the circuitry is soldered on. */
+ struct ssb_boardinfo {
+ 	u16 vendor;
+ 	u16 type;
+-	u8  rev;
+ };
+ 
+ 
 --- a/include/linux/ssb/ssb_driver_gige.h
 +++ b/include/linux/ssb/ssb_driver_gige.h
 @@ -2,6 +2,7 @@
@@ -544,8 +694,53 @@
  
 --- a/include/linux/ssb/ssb_regs.h
 +++ b/include/linux/ssb/ssb_regs.h
-@@ -432,6 +432,56 @@
+@@ -228,6 +228,7 @@
+ #define  SSB_SPROM1_AGAIN_BG_SHIFT	0
+ #define  SSB_SPROM1_AGAIN_A		0xFF00	/* A-PHY */
+ #define  SSB_SPROM1_AGAIN_A_SHIFT	8
++#define SSB_SPROM1_CCODE		0x0076
+ 
+ /* SPROM Revision 2 (inherits from rev 1) */
+ #define SSB_SPROM2_BFLHI		0x0038	/* Boardflags (high 16 bits) */
+@@ -267,6 +268,7 @@
+ #define  SSB_SPROM3_OFDMGPO		0x107A	/* G-PHY OFDM Power Offset (4 bytes, BigEndian) */
+ 
+ /* SPROM Revision 4 */
++#define SSB_SPROM4_BOARDREV		0x0042	/* Board revision */
+ #define SSB_SPROM4_BFLLO		0x0044	/* Boardflags (low 16 bits) */
+ #define SSB_SPROM4_BFLHI		0x0046  /* Board Flags Hi */
+ #define SSB_SPROM4_BFL2LO		0x0048	/* Board flags 2 (low 16 bits) */
+@@ -389,6 +391,11 @@
+ #define  SSB_SPROM8_GPIOB_P2		0x00FF	/* Pin 2 */
+ #define  SSB_SPROM8_GPIOB_P3		0xFF00	/* Pin 3 */
+ #define  SSB_SPROM8_GPIOB_P3_SHIFT	8
++#define SSB_SPROM8_LEDDC		0x009A
++#define  SSB_SPROM8_LEDDC_ON		0xFF00	/* oncount */
++#define  SSB_SPROM8_LEDDC_ON_SHIFT	8
++#define  SSB_SPROM8_LEDDC_OFF		0x00FF	/* offcount */
++#define  SSB_SPROM8_LEDDC_OFF_SHIFT	0
+ #define SSB_SPROM8_ANTAVAIL		0x009C  /* Antenna available bitfields*/
+ #define  SSB_SPROM8_ANTAVAIL_A		0xFF00	/* A-PHY bitfield */
+ #define  SSB_SPROM8_ANTAVAIL_A_SHIFT	8
+@@ -404,6 +411,13 @@
+ #define  SSB_SPROM8_AGAIN2_SHIFT	0
+ #define  SSB_SPROM8_AGAIN3		0xFF00	/* Antenna 3 */
+ #define  SSB_SPROM8_AGAIN3_SHIFT	8
++#define SSB_SPROM8_TXRXC		0x00A2
++#define  SSB_SPROM8_TXRXC_TXCHAIN	0x000f
++#define  SSB_SPROM8_TXRXC_TXCHAIN_SHIFT	0
++#define  SSB_SPROM8_TXRXC_RXCHAIN	0x00f0
++#define  SSB_SPROM8_TXRXC_RXCHAIN_SHIFT	4
++#define  SSB_SPROM8_TXRXC_SWITCH	0xff00
++#define  SSB_SPROM8_TXRXC_SWITCH_SHIFT	8
+ #define SSB_SPROM8_RSSIPARM2G		0x00A4	/* RSSI params for 2GHz */
+ #define  SSB_SPROM8_RSSISMF2G		0x000F
+ #define  SSB_SPROM8_RSSISMC2G		0x00F0
+@@ -430,8 +444,87 @@
+ #define  SSB_SPROM8_TRI5GH_SHIFT	8
+ #define SSB_SPROM8_RXPO			0x00AC  /* RX power offsets */
  #define  SSB_SPROM8_RXPO2G		0x00FF	/* 2GHz RX power offset */
++#define  SSB_SPROM8_RXPO2G_SHIFT	0
  #define  SSB_SPROM8_RXPO5G		0xFF00	/* 5GHz RX power offset */
  #define  SSB_SPROM8_RXPO5G_SHIFT	8
 +#define SSB_SPROM8_FEM2G		0x00AE
@@ -561,10 +756,38 @@
 +#define  SSB_SROM8_FEM_ANTSWLUT		0xF800
 +#define  SSB_SROM8_FEM_ANTSWLUT_SHIFT	11
 +#define SSB_SPROM8_THERMAL		0x00B2
-+#define SSB_SPROM8_MPWR_RAWTS		0x00B4
-+#define SSB_SPROM8_TS_SLP_OPT_CORRX	0x00B6
-+#define SSB_SPROM8_FOC_HWIQ_IQSWP	0x00B8
-+#define SSB_SPROM8_PHYCAL_TEMPDELTA	0x00BA
++#define  SSB_SPROM8_THERMAL_OFFSET	0x00ff
++#define  SSB_SPROM8_THERMAL_OFFSET_SHIFT	0
++#define  SSB_SPROM8_THERMAL_TRESH	0xff00
++#define  SSB_SPROM8_THERMAL_TRESH_SHIFT	8
++/* Temp sense related entries */
++#define SSB_SPROM8_RAWTS		0x00B4
++#define  SSB_SPROM8_RAWTS_RAWTEMP	0x01ff
++#define  SSB_SPROM8_RAWTS_RAWTEMP_SHIFT	0
++#define  SSB_SPROM8_RAWTS_MEASPOWER	0xfe00
++#define  SSB_SPROM8_RAWTS_MEASPOWER_SHIFT	9
++#define SSB_SPROM8_OPT_CORRX		0x00B6
++#define  SSB_SPROM8_OPT_CORRX_TEMP_SLOPE	0x00ff
++#define  SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT	0
++#define  SSB_SPROM8_OPT_CORRX_TEMPCORRX	0xfc00
++#define  SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT	10
++#define  SSB_SPROM8_OPT_CORRX_TEMP_OPTION	0x0300
++#define  SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT	8
++/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */
++#define SSB_SPROM8_HWIQ_IQSWP		0x00B8
++#define  SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR	0x000f
++#define  SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT	0
++#define  SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP	0x0010
++#define  SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT	4
++#define  SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL	0x0020
++#define  SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT	5
++#define SSB_SPROM8_TEMPDELTA		0x00BA
++#define  SSB_SPROM8_TEMPDELTA_PHYCAL	0x00ff
++#define  SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT	0
++#define  SSB_SPROM8_TEMPDELTA_PERIOD	0x0f00
++#define  SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT	8
++#define  SSB_SPROM8_TEMPDELTA_HYSTERESIS	0xf000
++#define  SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT	12
 +
 +/* There are 4 blocks with power info sharing the same layout */
 +#define SSB_SROM8_PWR_INFO_CORE0	0x00C0
@@ -601,7 +824,7 @@
  #define SSB_SPROM8_MAXP_BG		0x00C0  /* Max Power 2GHz in path 1 */
  #define  SSB_SPROM8_MAXP_BG_MASK	0x00FF  /* Mask for Max Power 2GHz */
  #define  SSB_SPROM8_ITSSI_BG		0xFF00	/* Mask for path 1 itssi_bg */
-@@ -456,6 +506,7 @@
+@@ -456,12 +549,23 @@
  #define SSB_SPROM8_PA1HIB0		0x00D8	/* 5.8GHz power amp settings */
  #define SSB_SPROM8_PA1HIB1		0x00DA
  #define SSB_SPROM8_PA1HIB2		0x00DC
@@ -609,3 +832,19 @@
  #define SSB_SPROM8_CCK2GPO		0x0140	/* CCK power offset */
  #define SSB_SPROM8_OFDM2GPO		0x0142	/* 2.4GHz OFDM power offset */
  #define SSB_SPROM8_OFDM5GPO		0x0146	/* 5.3GHz OFDM power offset */
+ #define SSB_SPROM8_OFDM5GLPO		0x014A	/* 5.2GHz OFDM power offset */
+ #define SSB_SPROM8_OFDM5GHPO		0x014E	/* 5.8GHz OFDM power offset */
+ 
++#define SSB_SPROM8_2G_MCSPO		0x0152
++#define SSB_SPROM8_5G_MCSPO		0x0162
++#define SSB_SPROM8_5GL_MCSPO		0x0172
++#define SSB_SPROM8_5GH_MCSPO		0x0182
++
++#define SSB_SPROM8_CDDPO		0x0192
++#define SSB_SPROM8_STBCPO		0x0194
++#define SSB_SPROM8_BW40PO		0x0196
++#define SSB_SPROM8_BWDUPPO		0x0198
++
+ /* Values for boardflags_lo read from SPROM */
+ #define SSB_BFL_BTCOEXIST		0x0001	/* implements Bluetooth coexistance */
+ #define SSB_BFL_PACTRL			0x0002	/* GPIO 9 controlling the PA */
diff --git a/target/linux/generic/patches-3.2/021-ssb_add_pci_id.patch b/target/linux/generic/patches-3.2/021-ssb_add_pci_id.patch
deleted file mode 100644
index 7cffebec48..0000000000
--- a/target/linux/generic/patches-3.2/021-ssb_add_pci_id.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/drivers/ssb/b43_pci_bridge.c
-+++ b/drivers/ssb/b43_pci_bridge.c
-@@ -29,6 +29,8 @@ static const struct pci_device_id b43_pc
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4322) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43222) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) },
diff --git a/target/linux/generic/patches-3.2/025-bcma_backport.patch b/target/linux/generic/patches-3.2/025-bcma_backport.patch
index fdb1b8dd2b..3149fd3ced 100644
--- a/target/linux/generic/patches-3.2/025-bcma_backport.patch
+++ b/target/linux/generic/patches-3.2/025-bcma_backport.patch
@@ -1,3 +1,14 @@
+--- a/drivers/bcma/Kconfig
++++ b/drivers/bcma/Kconfig
+@@ -29,7 +29,7 @@ config BCMA_HOST_PCI
+ 
+ config BCMA_DRIVER_PCI_HOSTMODE
+ 	bool "Driver for PCI core working in hostmode"
+-	depends on BCMA && MIPS
++	depends on BCMA && MIPS && BCMA_HOST_PCI
+ 	help
+ 	  PCI core hostmode operation (external PCI bus).
+ 
 --- a/drivers/bcma/bcma_private.h
 +++ b/drivers/bcma/bcma_private.h
 @@ -13,12 +13,13 @@
@@ -29,277 +40,25 @@
  #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
  
  #endif
---- a/drivers/bcma/host_pci.c
-+++ b/drivers/bcma/host_pci.c
-@@ -21,48 +21,58 @@ static void bcma_host_pci_switch_core(st
- 	pr_debug("Switched to core: 0x%X\n", core->id.id);
- }
- 
--static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset)
--{
-+/* Provides access to the requested core. Returns base offset that has to be
-+ * used. It makes use of fixed windows when possible. */
-+static u16 bcma_host_pci_provide_access_to_core(struct bcma_device *core)
-+{
-+	switch (core->id.id) {
-+	case BCMA_CORE_CHIPCOMMON:
-+		return 3 * BCMA_CORE_SIZE;
-+	case BCMA_CORE_PCIE:
-+		return 2 * BCMA_CORE_SIZE;
-+	}
-+
- 	if (core->bus->mapped_core != core)
- 		bcma_host_pci_switch_core(core);
-+	return 0;
-+}
-+
-+static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset)
-+{
-+	offset += bcma_host_pci_provide_access_to_core(core);
- 	return ioread8(core->bus->mmio + offset);
- }
- 
- static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset)
- {
--	if (core->bus->mapped_core != core)
--		bcma_host_pci_switch_core(core);
-+	offset += bcma_host_pci_provide_access_to_core(core);
- 	return ioread16(core->bus->mmio + offset);
- }
- 
- static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset)
- {
--	if (core->bus->mapped_core != core)
--		bcma_host_pci_switch_core(core);
-+	offset += bcma_host_pci_provide_access_to_core(core);
- 	return ioread32(core->bus->mmio + offset);
- }
- 
- static void bcma_host_pci_write8(struct bcma_device *core, u16 offset,
- 				 u8 value)
- {
--	if (core->bus->mapped_core != core)
--		bcma_host_pci_switch_core(core);
-+	offset += bcma_host_pci_provide_access_to_core(core);
- 	iowrite8(value, core->bus->mmio + offset);
- }
- 
- static void bcma_host_pci_write16(struct bcma_device *core, u16 offset,
- 				 u16 value)
- {
--	if (core->bus->mapped_core != core)
--		bcma_host_pci_switch_core(core);
-+	offset += bcma_host_pci_provide_access_to_core(core);
- 	iowrite16(value, core->bus->mmio + offset);
- }
- 
- static void bcma_host_pci_write32(struct bcma_device *core, u16 offset,
- 				 u32 value)
- {
--	if (core->bus->mapped_core != core)
--		bcma_host_pci_switch_core(core);
-+	offset += bcma_host_pci_provide_access_to_core(core);
- 	iowrite32(value, core->bus->mmio + offset);
- }
- 
-@@ -144,8 +154,8 @@ const struct bcma_host_ops bcma_host_pci
- 	.awrite32	= bcma_host_pci_awrite32,
- };
- 
--static int bcma_host_pci_probe(struct pci_dev *dev,
--			     const struct pci_device_id *id)
-+static int __devinit bcma_host_pci_probe(struct pci_dev *dev,
-+					 const struct pci_device_id *id)
- {
- 	struct bcma_bus *bus;
- 	int err = -ENOMEM;
-@@ -225,41 +235,32 @@ static void bcma_host_pci_remove(struct
- }
- 
- #ifdef CONFIG_PM
--static int bcma_host_pci_suspend(struct pci_dev *dev, pm_message_t state)
-+static int bcma_host_pci_suspend(struct device *dev)
- {
--	struct bcma_bus *bus = pci_get_drvdata(dev);
--
--	/* Host specific */
--	pci_save_state(dev);
--	pci_disable_device(dev);
--	pci_set_power_state(dev, pci_choose_state(dev, state));
-+	struct pci_dev *pdev = to_pci_dev(dev);
-+	struct bcma_bus *bus = pci_get_drvdata(pdev);
- 
- 	bus->mapped_core = NULL;
--	return 0;
-+
-+	return bcma_bus_suspend(bus);
- }
- 
--static int bcma_host_pci_resume(struct pci_dev *dev)
-+static int bcma_host_pci_resume(struct device *dev)
- {
--	struct bcma_bus *bus = pci_get_drvdata(dev);
--	int err;
-+	struct pci_dev *pdev = to_pci_dev(dev);
-+	struct bcma_bus *bus = pci_get_drvdata(pdev);
- 
--	/* Host specific */
--	pci_set_power_state(dev, 0);
--	err = pci_enable_device(dev);
--	if (err)
--		return err;
--	pci_restore_state(dev);
-+	return bcma_bus_resume(bus);
-+}
- 
--	/* Bus specific */
--	err = bcma_bus_resume(bus);
--	if (err)
--		return err;
-+static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend,
-+			 bcma_host_pci_resume);
-+#define BCMA_PM_OPS	(&bcma_pm_ops)
- 
--	return 0;
--}
- #else /* CONFIG_PM */
--# define bcma_host_pci_suspend	NULL
--# define bcma_host_pci_resume	NULL
-+
-+#define BCMA_PM_OPS     NULL
-+
- #endif /* CONFIG_PM */
- 
- static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
-@@ -277,8 +278,7 @@ static struct pci_driver bcma_pci_bridge
- 	.id_table = bcma_pci_bridge_tbl,
- 	.probe = bcma_host_pci_probe,
- 	.remove = bcma_host_pci_remove,
--	.suspend = bcma_host_pci_suspend,
--	.resume = bcma_host_pci_resume,
-+	.driver.pm = BCMA_PM_OPS,
- };
- 
- int __init bcma_host_pci_init(void)
---- a/drivers/bcma/main.c
-+++ b/drivers/bcma/main.c
-@@ -13,6 +13,12 @@
- MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
- MODULE_LICENSE("GPL");
- 
-+/* contains the number the next bus should get. */
-+static unsigned int bcma_bus_next_num = 0;
-+
-+/* bcma_buses_mutex locks the bcma_bus_next_num */
-+static DEFINE_MUTEX(bcma_buses_mutex);
-+
- static int bcma_bus_match(struct device *dev, struct device_driver *drv);
- static int bcma_device_probe(struct device *dev);
- static int bcma_device_remove(struct device *dev);
-@@ -55,7 +61,7 @@ static struct bus_type bcma_bus_type = {
- 	.dev_attrs	= bcma_device_attrs,
- };
- 
--static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
-+struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
- {
- 	struct bcma_device *core;
- 
-@@ -65,6 +71,7 @@ static struct bcma_device *bcma_find_cor
- 	}
- 	return NULL;
- }
-+EXPORT_SYMBOL_GPL(bcma_find_core);
- 
- static void bcma_release_core_dev(struct device *dev)
- {
-@@ -93,7 +100,7 @@ static int bcma_register_cores(struct bc
- 
- 		core->dev.release = bcma_release_core_dev;
- 		core->dev.bus = &bcma_bus_type;
--		dev_set_name(&core->dev, "bcma%d:%d", 0/*bus->num*/, dev_id);
-+		dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id);
- 
- 		switch (bus->hosttype) {
- 		case BCMA_HOSTTYPE_PCI:
-@@ -132,11 +139,15 @@ static void bcma_unregister_cores(struct
- 	}
- }
- 
--int bcma_bus_register(struct bcma_bus *bus)
-+int __devinit bcma_bus_register(struct bcma_bus *bus)
- {
- 	int err;
- 	struct bcma_device *core;
- 
-+	mutex_lock(&bcma_buses_mutex);
-+	bus->num = bcma_bus_next_num++;
-+	mutex_unlock(&bcma_buses_mutex);
-+
- 	/* Scan for devices (cores) */
- 	err = bcma_bus_scan(bus);
- 	if (err) {
-@@ -169,10 +180,8 @@ int bcma_bus_register(struct bcma_bus *b
- 	err = bcma_sprom_get(bus);
- 	if (err == -ENOENT) {
- 		pr_err("No SPROM available\n");
--	} else if (err) {
-+	} else if (err)
- 		pr_err("Failed to get SPROM: %d\n", err);
--		return -ENOENT;
--	}
+--- a/drivers/bcma/core.c
++++ b/drivers/bcma/core.c
+@@ -30,6 +30,7 @@ void bcma_core_disable(struct bcma_devic
+ 	udelay(10);
  
- 	/* Register found cores */
- 	bcma_register_cores(bus);
-@@ -241,6 +250,21 @@ int __init bcma_bus_early_register(struc
+ 	bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
++	bcma_aread32(core, BCMA_RESET_CTL);
+ 	udelay(1);
  }
- 
- #ifdef CONFIG_PM
-+int bcma_bus_suspend(struct bcma_bus *bus)
-+{
-+	struct bcma_device *core;
-+
-+	list_for_each_entry(core, &bus->cores, list) {
-+		struct device_driver *drv = core->dev.driver;
-+		if (drv) {
-+			struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
-+			if (adrv->suspend)
-+				adrv->suspend(core);
-+		}
-+	}
-+	return 0;
-+}
-+
- int bcma_bus_resume(struct bcma_bus *bus)
- {
- 	struct bcma_device *core;
-@@ -252,6 +276,15 @@ int bcma_bus_resume(struct bcma_bus *bus
- 		bcma_core_chipcommon_init(&bus->drv_cc);
+ EXPORT_SYMBOL_GPL(bcma_core_disable);
+@@ -77,7 +78,7 @@ void bcma_core_set_clockmode(struct bcma
+ 			pr_err("HT force timeout\n");
+ 		break;
+ 	case BCMA_CLKMODE_DYNAMIC:
+-		pr_warn("Dynamic clockmode not supported yet!\n");
++		bcma_set32(core, BCMA_CLKCTLST, ~BCMA_CLKCTLST_FORCEHT);
+ 		break;
  	}
- 
-+	list_for_each_entry(core, &bus->cores, list) {
-+		struct device_driver *drv = core->dev.driver;
-+		if (drv) {
-+			struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
-+			if (adrv->resume)
-+				adrv->resume(core);
-+		}
-+	}
-+
- 	return 0;
  }
- #endif
---- a/drivers/bcma/Kconfig
-+++ b/drivers/bcma/Kconfig
-@@ -29,7 +29,7 @@ config BCMA_HOST_PCI
- 
- config BCMA_DRIVER_PCI_HOSTMODE
- 	bool "Driver for PCI core working in hostmode"
--	depends on BCMA && MIPS
-+	depends on BCMA && MIPS && BCMA_HOST_PCI
- 	help
- 	  PCI core hostmode operation (external PCI bus).
- 
 --- a/drivers/bcma/driver_chipcommon_pmu.c
 +++ b/drivers/bcma/driver_chipcommon_pmu.c
 @@ -80,6 +80,7 @@ static void bcma_pmu_resources_init(stru
@@ -323,7 +82,7 @@
   *
   * Licensed under the GNU/GPL. See COPYING for details.
   */
-@@ -16,40 +17,41 @@
+@@ -16,40 +17,39 @@
   * R/W ops.
   **************************************************/
  
@@ -338,7 +97,7 @@
 +	return pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_DATA);
  }
  
- #if 0
+-#if 0
  static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data)
  {
 -	pcicore_write32(pc, 0x130, address);
@@ -348,7 +107,7 @@
 +	pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR);
 +	pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_DATA, data);
  }
- #endif
+-#endif
  
  static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy)
  {
@@ -381,7 +140,7 @@
  			break;
  		msleep(1);
  	}
-@@ -57,79 +59,84 @@ static void bcma_pcie_mdio_set_phy(struc
+@@ -57,79 +57,84 @@ static void bcma_pcie_mdio_set_phy(struc
  
  static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address)
  {
@@ -497,7 +256,7 @@
  }
  
  /**************************************************
-@@ -138,72 +145,53 @@ static void bcma_pcie_mdio_write(struct
+@@ -138,72 +143,90 @@ static void bcma_pcie_mdio_write(struct
  
  static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc)
  {
@@ -532,6 +291,41 @@
 +		bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL,
 +		                     BCMA_CORE_PCI_SERDES_PLL_CTRL,
 +		                     tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN);
++}
++
++static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc)
++{
++	struct bcma_device *core = pc->core;
++	u16 val16, core_index;
++	uint regoff;
++
++	regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_PI_OFFSET);
++	core_index = (u16)core->core_index;
++
++	val16 = pcicore_read16(pc, regoff);
++	if (((val16 & BCMA_CORE_PCI_SPROM_PI_MASK) >> BCMA_CORE_PCI_SPROM_PI_SHIFT)
++	     != core_index) {
++		val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) |
++			(val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK);
++		pcicore_write16(pc, regoff, val16);
++	}
++}
++
++/* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */
++/* Needs to happen when coming out of 'standby'/'hibernate' */
++static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc)
++{
++	u16 val16;
++	uint regoff;
++
++	regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_MISC_CONFIG);
++
++	val16 = pcicore_read16(pc, regoff);
++
++	if (!(val16 & BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST)) {
++		val16 |= BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST;
++		pcicore_write16(pc, regoff, val16);
++	}
  }
  
  /**************************************************
@@ -541,7 +335,9 @@
 -static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
 +static void __devinit bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
  {
++	bcma_core_pci_fixcfg(pc);
  	bcma_pcicore_serdes_workaround(pc);
++	bcma_core_pci_config_fixup(pc);
  }
  
 -static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
@@ -593,6 +389,24 @@
  }
  
  int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
+@@ -236,3 +259,17 @@ out:
+ 	return err;
+ }
+ EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
++
++void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend)
++{
++	u32 w;
++
++	w = bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG);
++	if (extend)
++		w |= BCMA_CORE_PCI_ASPMTIMER_EXTEND;
++	else
++		w &= ~BCMA_CORE_PCI_ASPMTIMER_EXTEND;
++	bcma_pcie_write(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG, w);
++	bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG);
++}
++EXPORT_SYMBOL_GPL(bcma_core_pci_extend_L1timer);
 --- a/drivers/bcma/driver_pci_host.c
 +++ b/drivers/bcma/driver_pci_host.c
 @@ -2,13 +2,588 @@
@@ -718,7 +532,7 @@
 +		if (unlikely(!addr))
 +			goto out;
 +		err = -ENOMEM;
-+		mmio = ioremap_nocache(addr, len);
++		mmio = ioremap_nocache(addr, sizeof(val));
 +		if (!mmio)
 +			goto out;
 +
@@ -770,7 +584,7 @@
 +			addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0;
 +			addr |= (func << 8);
 +			addr |= (off & 0xfc);
-+			mmio = ioremap_nocache(addr, len);
++			mmio = ioremap_nocache(addr, sizeof(val));
 +			if (!mmio)
 +				goto out;
 +		}
@@ -779,7 +593,7 @@
 +		if (unlikely(!addr))
 +			goto out;
 +		err = -ENOMEM;
-+		mmio = ioremap_nocache(addr, len);
++		mmio = ioremap_nocache(addr, sizeof(val));
 +		if (!mmio)
 +			goto out;
 +
@@ -1087,108 +901,486 @@
 +	/* Enable PCI interrupts */
 +	pcicore_write32(pc, BCMA_CORE_PCI_IMASK, BCMA_CORE_PCI_IMASK_INTA);
 +
-+	/* Ok, ready to run, register it to the system.
-+	 * The following needs change, if we want to port hostmode
-+	 * to non-MIPS platform. */
-+	io_map_base = (unsigned long)ioremap_nocache(BCMA_SOC_PCI_MEM,
-+						     0x04000000);
-+	pc_host->pci_controller.io_map_base = io_map_base;
-+	set_io_port_base(pc_host->pci_controller.io_map_base);
-+	/* Give some time to the PCI controller to configure itself with the new
-+	 * values. Not waiting at this point causes crashes of the machine. */
-+	mdelay(10);
-+	register_pci_controller(&pc_host->pci_controller);
-+	return;
++	/* Ok, ready to run, register it to the system.
++	 * The following needs change, if we want to port hostmode
++	 * to non-MIPS platform. */
++	io_map_base = (unsigned long)ioremap_nocache(pc_host->mem_resource.start,
++						     resource_size(&pc_host->mem_resource));
++	pc_host->pci_controller.io_map_base = io_map_base;
++	set_io_port_base(pc_host->pci_controller.io_map_base);
++	/* Give some time to the PCI controller to configure itself with the new
++	 * values. Not waiting at this point causes crashes of the machine. */
++	mdelay(10);
++	register_pci_controller(&pc_host->pci_controller);
++	return;
++}
++
++/* Early PCI fixup for a device on the PCI-core bridge. */
++static void bcma_core_pci_fixup_pcibridge(struct pci_dev *dev)
++{
++	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
++		/* This is not a device on the PCI-core bridge. */
++		return;
++	}
++	if (PCI_SLOT(dev->devfn) != 0)
++		return;
++
++	pr_info("PCI: Fixing up bridge %s\n", pci_name(dev));
++
++	/* Enable PCI bridge bus mastering and memory space */
++	pci_set_master(dev);
++	if (pcibios_enable_device(dev, ~0) < 0) {
++		pr_err("PCI: BCMA bridge enable failed\n");
++		return;
++	}
++
++	/* Enable PCI bridge BAR1 prefetch and burst */
++	pci_write_config_dword(dev, BCMA_PCI_BAR1_CONTROL, 3);
++}
++DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_pcibridge);
++
++/* Early PCI fixup for all PCI-cores to set the correct memory address. */
++static void bcma_core_pci_fixup_addresses(struct pci_dev *dev)
++{
++	struct resource *res;
++	int pos;
++
++	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
++		/* This is not a device on the PCI-core bridge. */
++		return;
++	}
++	if (PCI_SLOT(dev->devfn) == 0)
++		return;
++
++	pr_info("PCI: Fixing up addresses %s\n", pci_name(dev));
++
++	for (pos = 0; pos < 6; pos++) {
++		res = &dev->resource[pos];
++		if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM))
++			pci_assign_resource(dev, pos);
++	}
++}
++DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses);
++
++/* This function is called when doing a pci_enable_device().
++ * We must first check if the device is a device on the PCI-core bridge. */
++int bcma_core_pci_plat_dev_init(struct pci_dev *dev)
++{
++	struct bcma_drv_pci_host *pc_host;
++
++	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
++		/* This is not a device on the PCI-core bridge. */
++		return -ENODEV;
++	}
++	pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
++			       pci_ops);
++
++	pr_info("PCI: Fixing up device %s\n", pci_name(dev));
++
++	/* Fix up interrupt lines */
++	dev->irq = bcma_core_mips_irq(pc_host->pdev->core) + 2;
++	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
++
++	return 0;
++}
++EXPORT_SYMBOL(bcma_core_pci_plat_dev_init);
++
++/* PCI device IRQ mapping. */
++int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev)
++{
++	struct bcma_drv_pci_host *pc_host;
++
++	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
++		/* This is not a device on the PCI-core bridge. */
++		return -ENODEV;
++	}
++
++	pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
++			       pci_ops);
++	return bcma_core_mips_irq(pc_host->pdev->core) + 2;
+ }
++EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq);
+--- a/drivers/bcma/host_pci.c
++++ b/drivers/bcma/host_pci.c
+@@ -21,48 +21,58 @@ static void bcma_host_pci_switch_core(st
+ 	pr_debug("Switched to core: 0x%X\n", core->id.id);
+ }
+ 
+-static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset)
+-{
++/* Provides access to the requested core. Returns base offset that has to be
++ * used. It makes use of fixed windows when possible. */
++static u16 bcma_host_pci_provide_access_to_core(struct bcma_device *core)
++{
++	switch (core->id.id) {
++	case BCMA_CORE_CHIPCOMMON:
++		return 3 * BCMA_CORE_SIZE;
++	case BCMA_CORE_PCIE:
++		return 2 * BCMA_CORE_SIZE;
++	}
++
+ 	if (core->bus->mapped_core != core)
+ 		bcma_host_pci_switch_core(core);
++	return 0;
++}
++
++static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset)
++{
++	offset += bcma_host_pci_provide_access_to_core(core);
+ 	return ioread8(core->bus->mmio + offset);
+ }
+ 
+ static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset)
+ {
+-	if (core->bus->mapped_core != core)
+-		bcma_host_pci_switch_core(core);
++	offset += bcma_host_pci_provide_access_to_core(core);
+ 	return ioread16(core->bus->mmio + offset);
+ }
+ 
+ static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset)
+ {
+-	if (core->bus->mapped_core != core)
+-		bcma_host_pci_switch_core(core);
++	offset += bcma_host_pci_provide_access_to_core(core);
+ 	return ioread32(core->bus->mmio + offset);
+ }
+ 
+ static void bcma_host_pci_write8(struct bcma_device *core, u16 offset,
+ 				 u8 value)
+ {
+-	if (core->bus->mapped_core != core)
+-		bcma_host_pci_switch_core(core);
++	offset += bcma_host_pci_provide_access_to_core(core);
+ 	iowrite8(value, core->bus->mmio + offset);
+ }
+ 
+ static void bcma_host_pci_write16(struct bcma_device *core, u16 offset,
+ 				 u16 value)
+ {
+-	if (core->bus->mapped_core != core)
+-		bcma_host_pci_switch_core(core);
++	offset += bcma_host_pci_provide_access_to_core(core);
+ 	iowrite16(value, core->bus->mmio + offset);
+ }
+ 
+ static void bcma_host_pci_write32(struct bcma_device *core, u16 offset,
+ 				 u32 value)
+ {
+-	if (core->bus->mapped_core != core)
+-		bcma_host_pci_switch_core(core);
++	offset += bcma_host_pci_provide_access_to_core(core);
+ 	iowrite32(value, core->bus->mmio + offset);
+ }
+ 
+@@ -144,8 +154,8 @@ const struct bcma_host_ops bcma_host_pci
+ 	.awrite32	= bcma_host_pci_awrite32,
+ };
+ 
+-static int bcma_host_pci_probe(struct pci_dev *dev,
+-			     const struct pci_device_id *id)
++static int __devinit bcma_host_pci_probe(struct pci_dev *dev,
++					 const struct pci_device_id *id)
+ {
+ 	struct bcma_bus *bus;
+ 	int err = -ENOMEM;
+@@ -191,6 +201,9 @@ static int bcma_host_pci_probe(struct pc
+ 	bus->hosttype = BCMA_HOSTTYPE_PCI;
+ 	bus->ops = &bcma_host_pci_ops;
+ 
++	bus->boardinfo.vendor = bus->host_pci->subsystem_vendor;
++	bus->boardinfo.type = bus->host_pci->subsystem_device;
++
+ 	/* Register */
+ 	err = bcma_bus_register(bus);
+ 	if (err)
+@@ -212,7 +225,7 @@ err_kfree_bus:
+ 	return err;
+ }
+ 
+-static void bcma_host_pci_remove(struct pci_dev *dev)
++static void __devexit bcma_host_pci_remove(struct pci_dev *dev)
+ {
+ 	struct bcma_bus *bus = pci_get_drvdata(dev);
+ 
+@@ -225,41 +238,32 @@ static void bcma_host_pci_remove(struct
+ }
+ 
+ #ifdef CONFIG_PM
+-static int bcma_host_pci_suspend(struct pci_dev *dev, pm_message_t state)
++static int bcma_host_pci_suspend(struct device *dev)
+ {
+-	struct bcma_bus *bus = pci_get_drvdata(dev);
+-
+-	/* Host specific */
+-	pci_save_state(dev);
+-	pci_disable_device(dev);
+-	pci_set_power_state(dev, pci_choose_state(dev, state));
++	struct pci_dev *pdev = to_pci_dev(dev);
++	struct bcma_bus *bus = pci_get_drvdata(pdev);
+ 
+ 	bus->mapped_core = NULL;
+-	return 0;
++
++	return bcma_bus_suspend(bus);
+ }
+ 
+-static int bcma_host_pci_resume(struct pci_dev *dev)
++static int bcma_host_pci_resume(struct device *dev)
+ {
+-	struct bcma_bus *bus = pci_get_drvdata(dev);
+-	int err;
++	struct pci_dev *pdev = to_pci_dev(dev);
++	struct bcma_bus *bus = pci_get_drvdata(pdev);
+ 
+-	/* Host specific */
+-	pci_set_power_state(dev, 0);
+-	err = pci_enable_device(dev);
+-	if (err)
+-		return err;
+-	pci_restore_state(dev);
++	return bcma_bus_resume(bus);
 +}
+ 
+-	/* Bus specific */
+-	err = bcma_bus_resume(bus);
+-	if (err)
+-		return err;
++static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend,
++			 bcma_host_pci_resume);
++#define BCMA_PM_OPS	(&bcma_pm_ops)
+ 
+-	return 0;
+-}
+ #else /* CONFIG_PM */
+-# define bcma_host_pci_suspend	NULL
+-# define bcma_host_pci_resume	NULL
 +
-+/* Early PCI fixup for a device on the PCI-core bridge. */
-+static void bcma_core_pci_fixup_pcibridge(struct pci_dev *dev)
-+{
-+	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
-+		/* This is not a device on the PCI-core bridge. */
-+		return;
-+	}
-+	if (PCI_SLOT(dev->devfn) != 0)
-+		return;
++#define BCMA_PM_OPS     NULL
 +
-+	pr_info("PCI: Fixing up bridge %s\n", pci_name(dev));
+ #endif /* CONFIG_PM */
+ 
+ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
+@@ -276,9 +280,8 @@ static struct pci_driver bcma_pci_bridge
+ 	.name = "bcma-pci-bridge",
+ 	.id_table = bcma_pci_bridge_tbl,
+ 	.probe = bcma_host_pci_probe,
+-	.remove = bcma_host_pci_remove,
+-	.suspend = bcma_host_pci_suspend,
+-	.resume = bcma_host_pci_resume,
++	.remove = __devexit_p(bcma_host_pci_remove),
++	.driver.pm = BCMA_PM_OPS,
+ };
+ 
+ int __init bcma_host_pci_init(void)
+--- a/drivers/bcma/main.c
++++ b/drivers/bcma/main.c
+@@ -13,6 +13,12 @@
+ MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
+ MODULE_LICENSE("GPL");
+ 
++/* contains the number the next bus should get. */
++static unsigned int bcma_bus_next_num = 0;
 +
-+	/* Enable PCI bridge bus mastering and memory space */
-+	pci_set_master(dev);
-+	if (pcibios_enable_device(dev, ~0) < 0) {
-+		pr_err("PCI: BCMA bridge enable failed\n");
-+		return;
-+	}
++/* bcma_buses_mutex locks the bcma_bus_next_num */
++static DEFINE_MUTEX(bcma_buses_mutex);
 +
-+	/* Enable PCI bridge BAR1 prefetch and burst */
-+	pci_write_config_dword(dev, BCMA_PCI_BAR1_CONTROL, 3);
-+}
-+DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_pcibridge);
+ static int bcma_bus_match(struct device *dev, struct device_driver *drv);
+ static int bcma_device_probe(struct device *dev);
+ static int bcma_device_remove(struct device *dev);
+@@ -55,7 +61,7 @@ static struct bus_type bcma_bus_type = {
+ 	.dev_attrs	= bcma_device_attrs,
+ };
+ 
+-static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
++struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
+ {
+ 	struct bcma_device *core;
+ 
+@@ -65,6 +71,7 @@ static struct bcma_device *bcma_find_cor
+ 	}
+ 	return NULL;
+ }
++EXPORT_SYMBOL_GPL(bcma_find_core);
+ 
+ static void bcma_release_core_dev(struct device *dev)
+ {
+@@ -93,7 +100,7 @@ static int bcma_register_cores(struct bc
+ 
+ 		core->dev.release = bcma_release_core_dev;
+ 		core->dev.bus = &bcma_bus_type;
+-		dev_set_name(&core->dev, "bcma%d:%d", 0/*bus->num*/, dev_id);
++		dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id);
+ 
+ 		switch (bus->hosttype) {
+ 		case BCMA_HOSTTYPE_PCI:
+@@ -132,11 +139,15 @@ static void bcma_unregister_cores(struct
+ 	}
+ }
+ 
+-int bcma_bus_register(struct bcma_bus *bus)
++int __devinit bcma_bus_register(struct bcma_bus *bus)
+ {
+ 	int err;
+ 	struct bcma_device *core;
+ 
++	mutex_lock(&bcma_buses_mutex);
++	bus->num = bcma_bus_next_num++;
++	mutex_unlock(&bcma_buses_mutex);
 +
-+/* Early PCI fixup for all PCI-cores to set the correct memory address. */
-+static void bcma_core_pci_fixup_addresses(struct pci_dev *dev)
+ 	/* Scan for devices (cores) */
+ 	err = bcma_bus_scan(bus);
+ 	if (err) {
+@@ -169,10 +180,8 @@ int bcma_bus_register(struct bcma_bus *b
+ 	err = bcma_sprom_get(bus);
+ 	if (err == -ENOENT) {
+ 		pr_err("No SPROM available\n");
+-	} else if (err) {
++	} else if (err)
+ 		pr_err("Failed to get SPROM: %d\n", err);
+-		return -ENOENT;
+-	}
+ 
+ 	/* Register found cores */
+ 	bcma_register_cores(bus);
+@@ -241,6 +250,21 @@ int __init bcma_bus_early_register(struc
+ }
+ 
+ #ifdef CONFIG_PM
++int bcma_bus_suspend(struct bcma_bus *bus)
 +{
-+	struct resource *res;
-+	int pos;
-+
-+	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
-+		/* This is not a device on the PCI-core bridge. */
-+		return;
-+	}
-+	if (PCI_SLOT(dev->devfn) == 0)
-+		return;
-+
-+	pr_info("PCI: Fixing up addresses %s\n", pci_name(dev));
++	struct bcma_device *core;
 +
-+	for (pos = 0; pos < 6; pos++) {
-+		res = &dev->resource[pos];
-+		if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM))
-+			pci_assign_resource(dev, pos);
++	list_for_each_entry(core, &bus->cores, list) {
++		struct device_driver *drv = core->dev.driver;
++		if (drv) {
++			struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
++			if (adrv->suspend)
++				adrv->suspend(core);
++		}
 +	}
++	return 0;
 +}
-+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses);
-+
-+/* This function is called when doing a pci_enable_device().
-+ * We must first check if the device is a device on the PCI-core bridge. */
-+int bcma_core_pci_plat_dev_init(struct pci_dev *dev)
-+{
-+	struct bcma_drv_pci_host *pc_host;
 +
-+	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
-+		/* This is not a device on the PCI-core bridge. */
-+		return -ENODEV;
+ int bcma_bus_resume(struct bcma_bus *bus)
+ {
+ 	struct bcma_device *core;
+@@ -252,6 +276,15 @@ int bcma_bus_resume(struct bcma_bus *bus
+ 		bcma_core_chipcommon_init(&bus->drv_cc);
+ 	}
+ 
++	list_for_each_entry(core, &bus->cores, list) {
++		struct device_driver *drv = core->dev.driver;
++		if (drv) {
++			struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
++			if (adrv->resume)
++				adrv->resume(core);
++		}
 +	}
-+	pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
-+			       pci_ops);
 +
-+	pr_info("PCI: Fixing up device %s\n", pci_name(dev));
+ 	return 0;
+ }
+ #endif
+--- a/drivers/bcma/scan.c
++++ b/drivers/bcma/scan.c
+@@ -19,7 +19,14 @@ struct bcma_device_id_name {
+ 	u16 id;
+ 	const char *name;
+ };
+-struct bcma_device_id_name bcma_device_names[] = {
 +
-+	/* Fix up interrupt lines */
-+	dev->irq = bcma_core_mips_irq(pc_host->pdev->core) + 2;
-+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
++static const struct bcma_device_id_name bcma_arm_device_names[] = {
++	{ BCMA_CORE_ARM_1176, "ARM 1176" },
++	{ BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },
++	{ BCMA_CORE_ARM_CM3, "ARM CM3" },
++};
 +
-+	return 0;
-+}
-+EXPORT_SYMBOL(bcma_core_pci_plat_dev_init);
++static const struct bcma_device_id_name bcma_bcm_device_names[] = {
+ 	{ BCMA_CORE_OOB_ROUTER, "OOB Router" },
+ 	{ BCMA_CORE_INVALID, "Invalid" },
+ 	{ BCMA_CORE_CHIPCOMMON, "ChipCommon" },
+@@ -27,7 +34,6 @@ struct bcma_device_id_name bcma_device_n
+ 	{ BCMA_CORE_SRAM, "SRAM" },
+ 	{ BCMA_CORE_SDRAM, "SDRAM" },
+ 	{ BCMA_CORE_PCI, "PCI" },
+-	{ BCMA_CORE_MIPS, "MIPS" },
+ 	{ BCMA_CORE_ETHERNET, "Fast Ethernet" },
+ 	{ BCMA_CORE_V90, "V90" },
+ 	{ BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" },
+@@ -44,7 +50,6 @@ struct bcma_device_id_name bcma_device_n
+ 	{ BCMA_CORE_PHY_A, "PHY A" },
+ 	{ BCMA_CORE_PHY_B, "PHY B" },
+ 	{ BCMA_CORE_PHY_G, "PHY G" },
+-	{ BCMA_CORE_MIPS_3302, "MIPS 3302" },
+ 	{ BCMA_CORE_USB11_HOST, "USB 1.1 Host" },
+ 	{ BCMA_CORE_USB11_DEV, "USB 1.1 Device" },
+ 	{ BCMA_CORE_USB20_HOST, "USB 2.0 Host" },
+@@ -58,15 +63,11 @@ struct bcma_device_id_name bcma_device_n
+ 	{ BCMA_CORE_PHY_N, "PHY N" },
+ 	{ BCMA_CORE_SRAM_CTL, "SRAM Controller" },
+ 	{ BCMA_CORE_MINI_MACPHY, "Mini MACPHY" },
+-	{ BCMA_CORE_ARM_1176, "ARM 1176" },
+-	{ BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },
+ 	{ BCMA_CORE_PHY_LP, "PHY LP" },
+ 	{ BCMA_CORE_PMU, "PMU" },
+ 	{ BCMA_CORE_PHY_SSN, "PHY SSN" },
+ 	{ BCMA_CORE_SDIO_DEV, "SDIO Device" },
+-	{ BCMA_CORE_ARM_CM3, "ARM CM3" },
+ 	{ BCMA_CORE_PHY_HT, "PHY HT" },
+-	{ BCMA_CORE_MIPS_74K, "MIPS 74K" },
+ 	{ BCMA_CORE_MAC_GBIT, "GBit MAC" },
+ 	{ BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" },
+ 	{ BCMA_CORE_PCIE_RC, "PCIe Root Complex" },
+@@ -79,16 +80,41 @@ struct bcma_device_id_name bcma_device_n
+ 	{ BCMA_CORE_SHIM, "SHIM" },
+ 	{ BCMA_CORE_DEFAULT, "Default" },
+ };
+-const char *bcma_device_name(struct bcma_device_id *id)
 +
-+/* PCI device IRQ mapping. */
-+int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev)
-+{
-+	struct bcma_drv_pci_host *pc_host;
++static const struct bcma_device_id_name bcma_mips_device_names[] = {
++	{ BCMA_CORE_MIPS, "MIPS" },
++	{ BCMA_CORE_MIPS_3302, "MIPS 3302" },
++	{ BCMA_CORE_MIPS_74K, "MIPS 74K" },
++};
 +
-+	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
-+		/* This is not a device on the PCI-core bridge. */
-+		return -ENODEV;
++static const char *bcma_device_name(const struct bcma_device_id *id)
+ {
+-	int i;
++	const struct bcma_device_id_name *names;
++	int size, i;
+ 
+-	if (id->manuf == BCMA_MANUF_BCM) {
+-		for (i = 0; i < ARRAY_SIZE(bcma_device_names); i++) {
+-			if (bcma_device_names[i].id == id->id)
+-				return bcma_device_names[i].name;
+-		}
++	/* search manufacturer specific names */
++	switch (id->manuf) {
++	case BCMA_MANUF_ARM:
++		names = bcma_arm_device_names;
++		size = ARRAY_SIZE(bcma_arm_device_names);
++		break;
++	case BCMA_MANUF_BCM:
++		names = bcma_bcm_device_names;
++		size = ARRAY_SIZE(bcma_bcm_device_names);
++		break;
++	case BCMA_MANUF_MIPS:
++		names = bcma_mips_device_names;
++		size = ARRAY_SIZE(bcma_mips_device_names);
++		break;
++	default:
++		return "UNKNOWN";
 +	}
 +
-+	pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
-+			       pci_ops);
-+	return bcma_core_mips_irq(pc_host->pdev->core) + 2;
++	for (i = 0; i < size; i++) {
++		if (names[i].id == id->id)
++			return names[i].name;
+ 	}
++
+ 	return "UNKNOWN";
  }
-+EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq);
---- a/drivers/bcma/scan.c
-+++ b/drivers/bcma/scan.c
-@@ -212,6 +212,17 @@ static struct bcma_device *bcma_find_cor
+ 
+@@ -212,6 +238,17 @@ static struct bcma_device *bcma_find_cor
  	return NULL;
  }
  
@@ -1206,7 +1398,7 @@
  static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
  			      struct bcma_device_id *match, int core_num,
  			      struct bcma_device *core)
-@@ -353,6 +364,7 @@ static int bcma_get_next_core(struct bcm
+@@ -353,6 +390,7 @@ static int bcma_get_next_core(struct bcm
  void bcma_init_bus(struct bcma_bus *bus)
  {
  	s32 tmp;
@@ -1214,7 +1406,7 @@
  
  	if (bus->init_done)
  		return;
-@@ -363,9 +375,12 @@ void bcma_init_bus(struct bcma_bus *bus)
+@@ -363,9 +401,12 @@ void bcma_init_bus(struct bcma_bus *bus)
  	bcma_scan_switch_core(bus, BCMA_ADDR_BASE);
  
  	tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID);
@@ -1230,7 +1422,7 @@
  	bus->init_done = true;
  }
  
-@@ -392,6 +407,7 @@ int bcma_bus_scan(struct bcma_bus *bus)
+@@ -392,6 +433,7 @@ int bcma_bus_scan(struct bcma_bus *bus)
  	bcma_scan_switch_core(bus, erombase);
  
  	while (eromptr < eromend) {
@@ -1238,7 +1430,7 @@
  		struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL);
  		if (!core)
  			return -ENOMEM;
-@@ -399,18 +415,23 @@ int bcma_bus_scan(struct bcma_bus *bus)
+@@ -399,18 +441,23 @@ int bcma_bus_scan(struct bcma_bus *bus)
  		core->bus = bus;
  
  		err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core);
@@ -1340,7 +1532,7 @@
  
  /**************************************************
   * R/W ops.
-@@ -124,37 +176,253 @@ static int bcma_sprom_valid(const u16 *s
+@@ -124,37 +176,403 @@ static int bcma_sprom_valid(const u16 *s
   * SPROM extraction.
   **************************************************/
  
@@ -1348,6 +1540,22 @@
 +
 +#define SPEX(_field, _offset, _mask, _shift)	\
 +	bus->sprom._field = ((sprom[SPOFF(_offset)] & (_mask)) >> (_shift))
++
++#define SPEX32(_field, _offset, _mask, _shift)	\
++	bus->sprom._field = ((((u32)sprom[SPOFF((_offset)+2)] << 16 | \
++				sprom[SPOFF(_offset)]) & (_mask)) >> (_shift))
++
++#define SPEX_ARRAY8(_field, _offset, _mask, _shift)	\
++	do {	\
++		SPEX(_field[0], _offset +  0, _mask, _shift);	\
++		SPEX(_field[1], _offset +  2, _mask, _shift);	\
++		SPEX(_field[2], _offset +  4, _mask, _shift);	\
++		SPEX(_field[3], _offset +  6, _mask, _shift);	\
++		SPEX(_field[4], _offset +  8, _mask, _shift);	\
++		SPEX(_field[5], _offset + 10, _mask, _shift);	\
++		SPEX(_field[6], _offset + 12, _mask, _shift);	\
++		SPEX(_field[7], _offset + 14, _mask, _shift);	\
++	} while (0)
 +
  static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
  {
@@ -1417,7 +1625,8 @@
 +	SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, ~0, 0);
 +	SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, ~0, 0);
 +
-+	SPEX(country_code, SSB_SPROM8_CCODE, ~0, 0);
++	SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
++	SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
 +
 +	/* Extract cores power info info */
 +	for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
@@ -1472,6 +1681,136 @@
 +	     SSB_SROM8_FEM_TR_ISO_SHIFT);
 +	SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT,
 +	     SSB_SROM8_FEM_ANTSWLUT_SHIFT);
++
++	SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
++	     SSB_SPROM8_ANTAVAIL_A_SHIFT);
++	SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
++	     SSB_SPROM8_ANTAVAIL_BG_SHIFT);
++	SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
++	SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
++	     SSB_SPROM8_ITSSI_BG_SHIFT);
++	SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
++	SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
++	     SSB_SPROM8_ITSSI_A_SHIFT);
++	SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
++	SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
++	     SSB_SPROM8_MAXP_AL_SHIFT);
++	SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
++	SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
++	     SSB_SPROM8_GPIOA_P1_SHIFT);
++	SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
++	SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
++	     SSB_SPROM8_GPIOB_P3_SHIFT);
++	SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
++	SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
++	     SSB_SPROM8_TRI5G_SHIFT);
++	SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
++	SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
++	     SSB_SPROM8_TRI5GH_SHIFT);
++	SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G,
++	     SSB_SPROM8_RXPO2G_SHIFT);
++	SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
++	     SSB_SPROM8_RXPO5G_SHIFT);
++	SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
++	SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
++	     SSB_SPROM8_RSSISMC2G_SHIFT);
++	SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
++	     SSB_SPROM8_RSSISAV2G_SHIFT);
++	SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
++	     SSB_SPROM8_BXA2G_SHIFT);
++	SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
++	SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
++	     SSB_SPROM8_RSSISMC5G_SHIFT);
++	SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
++	     SSB_SPROM8_RSSISAV5G_SHIFT);
++	SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
++	     SSB_SPROM8_BXA5G_SHIFT);
++
++	SPEX(pa0b0, SSB_SPROM8_PA0B0, ~0, 0);
++	SPEX(pa0b1, SSB_SPROM8_PA0B1, ~0, 0);
++	SPEX(pa0b2, SSB_SPROM8_PA0B2, ~0, 0);
++	SPEX(pa1b0, SSB_SPROM8_PA1B0, ~0, 0);
++	SPEX(pa1b1, SSB_SPROM8_PA1B1, ~0, 0);
++	SPEX(pa1b2, SSB_SPROM8_PA1B2, ~0, 0);
++	SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, ~0, 0);
++	SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, ~0, 0);
++	SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, ~0, 0);
++	SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, ~0, 0);
++	SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, ~0, 0);
++	SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, ~0, 0);
++	SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, ~0, 0);
++	SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, ~0, 0);
++	SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, ~0, 0);
++	SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, ~0, 0);
++	SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0);
++
++	/* Extract the antenna gain values. */
++	SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
++	     SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
++	SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
++	     SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
++	SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
++	     SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
++	SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
++	     SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
++
++	SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
++	     SSB_SPROM8_LEDDC_ON_SHIFT);
++	SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
++	     SSB_SPROM8_LEDDC_OFF_SHIFT);
++
++	SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
++	     SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
++	SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
++	     SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
++	SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
++	     SSB_SPROM8_TXRXC_SWITCH_SHIFT);
++
++	SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
++
++	SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
++
++	SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
++	     SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
++	SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
++	     SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
++	SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
++	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
++	SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
++	SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
++	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
++	SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
++	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
++	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
++	SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
++	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
++	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
++	SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
++	     SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
++
++	SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
++	SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
++	SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
++	SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
++
++	SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
++	     SSB_SPROM8_THERMAL_TRESH_SHIFT);
++	SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
++	     SSB_SPROM8_THERMAL_OFFSET_SHIFT);
++	SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
++	     SSB_SPROM8_TEMPDELTA_PHYCAL,
++	     SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
++	SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
++	     SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
++	SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
++	     SSB_SPROM8_TEMPDELTA_HYSTERESIS,
++	     SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
 +}
 +
 +/*
@@ -1491,7 +1830,8 @@
 +					   BCMA_CC_SROM_CONTROL);
 +		return srom_control & BCMA_CC_SROM_CONTROL_PRESENT;
 +	}
-+
+ 
+-	bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)];
 +	/* older chipcommon revisions use chip status register */
 +	chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
 +	switch (bus->chipinfo.id) {
@@ -1539,8 +1879,7 @@
 +		present = false;
 +		break;
 +	}
- 
--	bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)];
++
 +	if (present) {
 +		otpsize = bus->drv_cc.capabilities & BCMA_CC_CAP_OTPS;
 +		otpsize >>= BCMA_CC_CAP_OTPS_SHIFT;
@@ -1582,16 +1921,19 @@
 -	if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
 -		return -ENOENT;
 +	if (!bcma_sprom_ext_available(bus)) {
++		bool sprom_onchip;
++
 +		/*
 +		 * External SPROM takes precedence so check
 +		 * on-chip OTP only when no external SPROM
 +		 * is present.
 +		 */
-+		if (bcma_sprom_onchip_available(bus)) {
++		sprom_onchip = bcma_sprom_onchip_available(bus);
++		if (sprom_onchip) {
 +			/* determine offset */
 +			offset = bcma_sprom_onchip_offset(bus);
 +		}
-+		if (!offset) {
++		if (!offset || !sprom_onchip) {
 +			/*
 +			 * Maybe there is no SPROM on the device?
 +			 * Now we ask the arch code if there is some sprom
@@ -1604,7 +1946,7 @@
  
  	sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
  			GFP_KERNEL);
-@@ -164,11 +432,7 @@ int bcma_sprom_get(struct bcma_bus *bus)
+@@ -164,11 +582,7 @@ int bcma_sprom_get(struct bcma_bus *bus)
  	if (bus->chipinfo.id == 0x4331)
  		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
  
@@ -1619,7 +1961,19 @@
  	if (bus->chipinfo.id == 0x4331)
 --- a/include/linux/bcma/bcma.h
 +++ b/include/linux/bcma/bcma.h
-@@ -136,6 +136,7 @@ struct bcma_device {
+@@ -26,6 +26,11 @@ struct bcma_chipinfo {
+ 	u8 pkg;
+ };
+ 
++struct bcma_boardinfo {
++	u16 vendor;
++	u16 type;
++};
++
+ enum bcma_clkmode {
+ 	BCMA_CLKMODE_FAST,
+ 	BCMA_CLKMODE_DYNAMIC,
+@@ -136,6 +141,7 @@ struct bcma_device {
  	bool dev_registered;
  
  	u8 core_index;
@@ -1627,7 +1981,7 @@
  
  	u32 addr;
  	u32 wrap;
-@@ -162,7 +163,7 @@ struct bcma_driver {
+@@ -162,7 +168,7 @@ struct bcma_driver {
  
  	int (*probe)(struct bcma_device *dev);
  	void (*remove)(struct bcma_device *dev);
@@ -1636,7 +1990,7 @@
  	int (*resume)(struct bcma_device *dev);
  	void (*shutdown)(struct bcma_device *dev);
  
-@@ -175,6 +176,12 @@ int __bcma_driver_register(struct bcma_d
+@@ -175,6 +181,12 @@ int __bcma_driver_register(struct bcma_d
  
  extern void bcma_driver_unregister(struct bcma_driver *drv);
  
@@ -1649,7 +2003,13 @@
  struct bcma_bus {
  	/* The MMIO area. */
  	void __iomem *mmio;
-@@ -195,6 +202,7 @@ struct bcma_bus {
+@@ -191,10 +203,13 @@ struct bcma_bus {
+ 
+ 	struct bcma_chipinfo chipinfo;
+ 
++	struct bcma_boardinfo boardinfo;
++
+ 	struct bcma_device *mapped_core;
  	struct list_head cores;
  	u8 nr_cores;
  	u8 init_done:1;
@@ -1657,7 +2017,7 @@
  
  	struct bcma_drv_cc drv_cc;
  	struct bcma_drv_pci drv_pci;
-@@ -205,62 +213,84 @@ struct bcma_bus {
+@@ -205,62 +220,84 @@ struct bcma_bus {
  	struct ssb_sprom sprom;
  };
  
@@ -1832,7 +2192,7 @@
  #define BCMA_CC_PMU5_MAINPLL_CPU	1
 --- a/include/linux/bcma/bcma_driver_pci.h
 +++ b/include/linux/bcma/bcma_driver_pci.h
-@@ -53,6 +53,35 @@ struct pci_dev;
+@@ -53,11 +53,47 @@ struct pci_dev;
  #define  BCMA_CORE_PCI_SBTOPCI1_MASK		0xFC000000
  #define BCMA_CORE_PCI_SBTOPCI2			0x0108	/* Backplane to PCI translation 2 (sbtopci2) */
  #define  BCMA_CORE_PCI_SBTOPCI2_MASK		0xC0000000
@@ -1868,7 +2228,19 @@
  #define BCMA_CORE_PCI_PCICFG0			0x0400	/* PCI config space 0 (rev >= 8) */
  #define BCMA_CORE_PCI_PCICFG1			0x0500	/* PCI config space 1 (rev >= 8) */
  #define BCMA_CORE_PCI_PCICFG2			0x0600	/* PCI config space 2 (rev >= 8) */
-@@ -72,20 +101,114 @@ struct pci_dev;
+ #define BCMA_CORE_PCI_PCICFG3			0x0700	/* PCI config space 3 (rev >= 8) */
+ #define BCMA_CORE_PCI_SPROM(wordoffset)		(0x0800 + ((wordoffset) * 2)) /* SPROM shadow area (72 bytes) */
++#define  BCMA_CORE_PCI_SPROM_PI_OFFSET		0	/* first word */
++#define   BCMA_CORE_PCI_SPROM_PI_MASK		0xf000	/* bit 15:12 */
++#define   BCMA_CORE_PCI_SPROM_PI_SHIFT		12	/* bit 15:12 */
++#define  BCMA_CORE_PCI_SPROM_MISC_CONFIG	5	/* word 5 */
++#define   BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST	0x8000	/* bit 15 */
++#define   BCMA_CORE_PCI_SPROM_CLKREQ_OFFSET_REV5	20	/* word 20 for srom rev <= 5 */
++#define   BCMA_CORE_PCI_SPROM_CLKREQ_ENB	0x0800	/* bit 11 */
+ 
+ /* SBtoPCIx */
+ #define BCMA_CORE_PCI_SBTOPCI_MEM		0x00000000
+@@ -72,20 +108,118 @@ struct pci_dev;
  #define  BCMA_CORE_PCI_SBTOPCI_RC_READL		0x00000010 /* Memory read line */
  #define  BCMA_CORE_PCI_SBTOPCI_RC_READM		0x00000020 /* Memory read multiple */
  
@@ -1904,6 +2276,7 @@
 +#define BCMA_CORE_PCI_DLLP_LRREG		0x120	/* Link Replay */
 +#define BCMA_CORE_PCI_DLLP_LACKTOREG		0x124	/* Link Ack Timeout */
 +#define BCMA_CORE_PCI_DLLP_PMTHRESHREG		0x128	/* Power Management Threshold */
++#define  BCMA_CORE_PCI_ASPMTIMER_EXTEND		0x01000000 /* > rev7: enable extend ASPM timer */
 +#define BCMA_CORE_PCI_DLLP_RTRYWPREG		0x12C	/* Retry buffer write ptr */
 +#define BCMA_CORE_PCI_DLLP_RTRYRPREG		0x130	/* Retry buffer Read ptr */
 +#define BCMA_CORE_PCI_DLLP_RTRYPPREG		0x134	/* Retry buffer Purged ptr */
@@ -1972,17 +2345,20 @@
  };
  
  /* Register access */
++#define pcicore_read16(pc, offset)		bcma_read16((pc)->core, offset)
  #define pcicore_read32(pc, offset)		bcma_read32((pc)->core, offset)
++#define pcicore_write16(pc, offset, val)	bcma_write16((pc)->core, offset, val)
  #define pcicore_write32(pc, offset, val)	bcma_write32((pc)->core, offset, val)
  
 -extern void bcma_core_pci_init(struct bcma_drv_pci *pc);
 +extern void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc);
  extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
  				 struct bcma_device *core, bool enable);
- 
++extern void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend);
++
 +extern int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev);
 +extern int bcma_core_pci_plat_dev_init(struct pci_dev *dev);
-+
+ 
  #endif /* LINUX_BCMA_DRIVER_PCI_H_ */
 --- a/include/linux/bcma/bcma_regs.h
 +++ b/include/linux/bcma/bcma_regs.h
diff --git a/target/linux/generic/patches-3.3/020-ssb_update.patch b/target/linux/generic/patches-3.3/020-ssb_update.patch
index 708c7ded34..01e087a316 100644
--- a/target/linux/generic/patches-3.3/020-ssb_update.patch
+++ b/target/linux/generic/patches-3.3/020-ssb_update.patch
@@ -1,3 +1,14 @@
+--- a/drivers/ssb/b43_pci_bridge.c
++++ b/drivers/ssb/b43_pci_bridge.c
+@@ -29,6 +29,8 @@ static const struct pci_device_id b43_pc
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4322) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43222) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) },
 --- a/drivers/ssb/driver_chipcommon_pmu.c
 +++ b/drivers/ssb/driver_chipcommon_pmu.c
 @@ -13,6 +13,9 @@
@@ -149,7 +160,26 @@
  					   &clkctl_n, &clkctl_m);
 --- a/drivers/ssb/pci.c
 +++ b/drivers/ssb/pci.c
-@@ -331,7 +331,6 @@ static void sprom_extract_r123(struct ss
+@@ -178,6 +178,18 @@ err_pci:
+ #define SPEX(_outvar, _offset, _mask, _shift) \
+ 	SPEX16(_outvar, _offset, _mask, _shift)
+ 
++#define SPEX_ARRAY8(_field, _offset, _mask, _shift)	\
++	do {	\
++		SPEX(_field[0], _offset +  0, _mask, _shift);	\
++		SPEX(_field[1], _offset +  2, _mask, _shift);	\
++		SPEX(_field[2], _offset +  4, _mask, _shift);	\
++		SPEX(_field[3], _offset +  6, _mask, _shift);	\
++		SPEX(_field[4], _offset +  8, _mask, _shift);	\
++		SPEX(_field[5], _offset + 10, _mask, _shift);	\
++		SPEX(_field[6], _offset + 12, _mask, _shift);	\
++		SPEX(_field[7], _offset + 14, _mask, _shift);	\
++	} while (0)
++
+ 
+ static inline u8 ssb_crc8(u8 crc, u8 data)
+ {
+@@ -331,7 +343,6 @@ static void sprom_extract_r123(struct ss
  {
  	int i;
  	u16 v;
@@ -157,8 +187,24 @@
  	u16 loc[3];
  
  	if (out->revision == 3)			/* rev 3 moved MAC */
-@@ -390,20 +389,12 @@ static void sprom_extract_r123(struct ss
+@@ -361,8 +372,9 @@ static void sprom_extract_r123(struct ss
+ 	SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
+ 	SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
+ 	SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
+-	SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
+-	     SSB_SPROM1_BINF_CCODE_SHIFT);
++	if (out->revision == 1)
++		SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
++		     SSB_SPROM1_BINF_CCODE_SHIFT);
+ 	SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
+ 	     SSB_SPROM1_BINF_ANTA_SHIFT);
+ 	SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
+@@ -388,22 +400,16 @@ static void sprom_extract_r123(struct ss
+ 	SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
+ 	if (out->revision >= 2)
  		SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
++	SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
++	SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
  
  	/* Extract the antenna gain values. */
 -	gain = r123_extract_antgain(out->revision, in,
@@ -184,7 +230,27 @@
  }
  
  /* Revs 4 5 and 8 have partially shared layout */
-@@ -504,16 +495,14 @@ static void sprom_extract_r45(struct ssb
+@@ -464,14 +470,17 @@ static void sprom_extract_r45(struct ssb
+ 	SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
+ 	SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
+ 	     SSB_SPROM4_ETHPHY_ET1A_SHIFT);
++	SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
+ 	if (out->revision == 4) {
+-		SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
++		SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
++		SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
+ 		SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
+ 		SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
+ 		SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
+ 		SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
+ 	} else {
+-		SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0);
++		SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8);
++		SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0);
+ 		SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
+ 		SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
+ 		SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
+@@ -504,16 +513,14 @@ static void sprom_extract_r45(struct ssb
  	}
  
  	/* Extract the antenna gain values. */
@@ -205,7 +271,7 @@
  
  	sprom_extract_r458(out, in);
  
-@@ -523,7 +512,13 @@ static void sprom_extract_r45(struct ssb
+@@ -523,14 +530,22 @@ static void sprom_extract_r45(struct ssb
  static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
  {
  	int i;
@@ -220,7 +286,17 @@
  
  	/* extract the MAC address */
  	for (i = 0; i < 3; i++) {
-@@ -596,16 +591,46 @@ static void sprom_extract_r8(struct ssb_
+ 		v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
+ 		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
+ 	}
+-	SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
++	SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
++	SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
++	SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
+ 	SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
+ 	SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
+ 	SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
+@@ -596,16 +611,46 @@ static void sprom_extract_r8(struct ssb_
  	SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
  
  	/* Extract the antenna gain values. */
@@ -273,6 +349,78 @@
  
  	/* Extract FEM info */
  	SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G,
+@@ -630,6 +675,63 @@ static void sprom_extract_r8(struct ssb_
+ 	SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
+ 		SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
+ 
++	SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
++	     SSB_SPROM8_LEDDC_ON_SHIFT);
++	SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
++	     SSB_SPROM8_LEDDC_OFF_SHIFT);
++
++	SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
++	     SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
++	SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
++	     SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
++	SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
++	     SSB_SPROM8_TXRXC_SWITCH_SHIFT);
++
++	SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
++
++	SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
++
++	SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
++	     SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
++	SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
++	     SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
++	SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
++	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
++	SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
++	SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
++	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
++	SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
++	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
++	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
++	SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
++	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
++	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
++	SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
++	     SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
++
++	SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
++	SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
++	SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
++	SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
++
++	SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
++	     SSB_SPROM8_THERMAL_TRESH_SHIFT);
++	SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
++	     SSB_SPROM8_THERMAL_OFFSET_SHIFT);
++	SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
++	     SSB_SPROM8_TEMPDELTA_PHYCAL,
++	     SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
++	SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
++	     SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
++	SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
++	     SSB_SPROM8_TEMPDELTA_HYSTERESIS,
++	     SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
+ 	sprom_extract_r458(out, in);
+ 
+ 	/* TODO - get remaining rev 8 stuff needed */
+@@ -759,7 +861,6 @@ static void ssb_pci_get_boardinfo(struct
+ {
+ 	bi->vendor = bus->host_pci->subsystem_vendor;
+ 	bi->type = bus->host_pci->subsystem_device;
+-	bi->rev = bus->host_pci->revision;
+ }
+ 
+ int ssb_pci_get_invariants(struct ssb_bus *bus,
 --- a/drivers/ssb/pcmcia.c
 +++ b/drivers/ssb/pcmcia.c
 @@ -676,14 +676,10 @@ static int ssb_pcmcia_do_get_invariants(
@@ -414,7 +562,7 @@
  	} antenna_gain;
  
  	struct {
-@@ -103,7 +109,79 @@ struct ssb_sprom {
+@@ -103,14 +109,85 @@ struct ssb_sprom {
  		} ghz5;
  	} fem;
  
@@ -495,6 +643,13 @@
  };
  
  /* Information about the PCB the circuitry is soldered on. */
+ struct ssb_boardinfo {
+ 	u16 vendor;
+ 	u16 type;
+-	u8  rev;
+ };
+ 
+ 
 --- a/include/linux/ssb/ssb_driver_gige.h
 +++ b/include/linux/ssb/ssb_driver_gige.h
 @@ -2,6 +2,7 @@
@@ -507,10 +662,96 @@
  
 --- a/include/linux/ssb/ssb_regs.h
 +++ b/include/linux/ssb/ssb_regs.h
-@@ -449,6 +449,39 @@
- #define SSB_SPROM8_TS_SLP_OPT_CORRX	0x00B6
- #define SSB_SPROM8_FOC_HWIQ_IQSWP	0x00B8
- #define SSB_SPROM8_PHYCAL_TEMPDELTA	0x00BA
+@@ -228,6 +228,7 @@
+ #define  SSB_SPROM1_AGAIN_BG_SHIFT	0
+ #define  SSB_SPROM1_AGAIN_A		0xFF00	/* A-PHY */
+ #define  SSB_SPROM1_AGAIN_A_SHIFT	8
++#define SSB_SPROM1_CCODE		0x0076
+ 
+ /* SPROM Revision 2 (inherits from rev 1) */
+ #define SSB_SPROM2_BFLHI		0x0038	/* Boardflags (high 16 bits) */
+@@ -267,6 +268,7 @@
+ #define  SSB_SPROM3_OFDMGPO		0x107A	/* G-PHY OFDM Power Offset (4 bytes, BigEndian) */
+ 
+ /* SPROM Revision 4 */
++#define SSB_SPROM4_BOARDREV		0x0042	/* Board revision */
+ #define SSB_SPROM4_BFLLO		0x0044	/* Boardflags (low 16 bits) */
+ #define SSB_SPROM4_BFLHI		0x0046  /* Board Flags Hi */
+ #define SSB_SPROM4_BFL2LO		0x0048	/* Board flags 2 (low 16 bits) */
+@@ -389,6 +391,11 @@
+ #define  SSB_SPROM8_GPIOB_P2		0x00FF	/* Pin 2 */
+ #define  SSB_SPROM8_GPIOB_P3		0xFF00	/* Pin 3 */
+ #define  SSB_SPROM8_GPIOB_P3_SHIFT	8
++#define SSB_SPROM8_LEDDC		0x009A
++#define  SSB_SPROM8_LEDDC_ON		0xFF00	/* oncount */
++#define  SSB_SPROM8_LEDDC_ON_SHIFT	8
++#define  SSB_SPROM8_LEDDC_OFF		0x00FF	/* offcount */
++#define  SSB_SPROM8_LEDDC_OFF_SHIFT	0
+ #define SSB_SPROM8_ANTAVAIL		0x009C  /* Antenna available bitfields*/
+ #define  SSB_SPROM8_ANTAVAIL_A		0xFF00	/* A-PHY bitfield */
+ #define  SSB_SPROM8_ANTAVAIL_A_SHIFT	8
+@@ -404,6 +411,13 @@
+ #define  SSB_SPROM8_AGAIN2_SHIFT	0
+ #define  SSB_SPROM8_AGAIN3		0xFF00	/* Antenna 3 */
+ #define  SSB_SPROM8_AGAIN3_SHIFT	8
++#define SSB_SPROM8_TXRXC		0x00A2
++#define  SSB_SPROM8_TXRXC_TXCHAIN	0x000f
++#define  SSB_SPROM8_TXRXC_TXCHAIN_SHIFT	0
++#define  SSB_SPROM8_TXRXC_RXCHAIN	0x00f0
++#define  SSB_SPROM8_TXRXC_RXCHAIN_SHIFT	4
++#define  SSB_SPROM8_TXRXC_SWITCH	0xff00
++#define  SSB_SPROM8_TXRXC_SWITCH_SHIFT	8
+ #define SSB_SPROM8_RSSIPARM2G		0x00A4	/* RSSI params for 2GHz */
+ #define  SSB_SPROM8_RSSISMF2G		0x000F
+ #define  SSB_SPROM8_RSSISMC2G		0x00F0
+@@ -430,6 +444,7 @@
+ #define  SSB_SPROM8_TRI5GH_SHIFT	8
+ #define SSB_SPROM8_RXPO			0x00AC  /* RX power offsets */
+ #define  SSB_SPROM8_RXPO2G		0x00FF	/* 2GHz RX power offset */
++#define  SSB_SPROM8_RXPO2G_SHIFT	0
+ #define  SSB_SPROM8_RXPO5G		0xFF00	/* 5GHz RX power offset */
+ #define  SSB_SPROM8_RXPO5G_SHIFT	8
+ #define SSB_SPROM8_FEM2G		0x00AE
+@@ -445,10 +460,71 @@
+ #define  SSB_SROM8_FEM_ANTSWLUT		0xF800
+ #define  SSB_SROM8_FEM_ANTSWLUT_SHIFT	11
+ #define SSB_SPROM8_THERMAL		0x00B2
+-#define SSB_SPROM8_MPWR_RAWTS		0x00B4
+-#define SSB_SPROM8_TS_SLP_OPT_CORRX	0x00B6
+-#define SSB_SPROM8_FOC_HWIQ_IQSWP	0x00B8
+-#define SSB_SPROM8_PHYCAL_TEMPDELTA	0x00BA
++#define  SSB_SPROM8_THERMAL_OFFSET	0x00ff
++#define  SSB_SPROM8_THERMAL_OFFSET_SHIFT	0
++#define  SSB_SPROM8_THERMAL_TRESH	0xff00
++#define  SSB_SPROM8_THERMAL_TRESH_SHIFT	8
++/* Temp sense related entries */
++#define SSB_SPROM8_RAWTS		0x00B4
++#define  SSB_SPROM8_RAWTS_RAWTEMP	0x01ff
++#define  SSB_SPROM8_RAWTS_RAWTEMP_SHIFT	0
++#define  SSB_SPROM8_RAWTS_MEASPOWER	0xfe00
++#define  SSB_SPROM8_RAWTS_MEASPOWER_SHIFT	9
++#define SSB_SPROM8_OPT_CORRX		0x00B6
++#define  SSB_SPROM8_OPT_CORRX_TEMP_SLOPE	0x00ff
++#define  SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT	0
++#define  SSB_SPROM8_OPT_CORRX_TEMPCORRX	0xfc00
++#define  SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT	10
++#define  SSB_SPROM8_OPT_CORRX_TEMP_OPTION	0x0300
++#define  SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT	8
++/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */
++#define SSB_SPROM8_HWIQ_IQSWP		0x00B8
++#define  SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR	0x000f
++#define  SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT	0
++#define  SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP	0x0010
++#define  SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT	4
++#define  SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL	0x0020
++#define  SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT	5
++#define SSB_SPROM8_TEMPDELTA		0x00BA
++#define  SSB_SPROM8_TEMPDELTA_PHYCAL	0x00ff
++#define  SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT	0
++#define  SSB_SPROM8_TEMPDELTA_PERIOD	0x0f00
++#define  SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT	8
++#define  SSB_SPROM8_TEMPDELTA_HYSTERESIS	0xf000
++#define  SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT	12
 +
 +/* There are 4 blocks with power info sharing the same layout */
 +#define SSB_SROM8_PWR_INFO_CORE0	0x00C0
@@ -547,7 +788,7 @@
  #define SSB_SPROM8_MAXP_BG		0x00C0  /* Max Power 2GHz in path 1 */
  #define  SSB_SPROM8_MAXP_BG_MASK	0x00FF  /* Mask for Max Power 2GHz */
  #define  SSB_SPROM8_ITSSI_BG		0xFF00	/* Mask for path 1 itssi_bg */
-@@ -473,6 +506,7 @@
+@@ -473,12 +549,23 @@
  #define SSB_SPROM8_PA1HIB0		0x00D8	/* 5.8GHz power amp settings */
  #define SSB_SPROM8_PA1HIB1		0x00DA
  #define SSB_SPROM8_PA1HIB2		0x00DC
@@ -555,3 +796,19 @@
  #define SSB_SPROM8_CCK2GPO		0x0140	/* CCK power offset */
  #define SSB_SPROM8_OFDM2GPO		0x0142	/* 2.4GHz OFDM power offset */
  #define SSB_SPROM8_OFDM5GPO		0x0146	/* 5.3GHz OFDM power offset */
+ #define SSB_SPROM8_OFDM5GLPO		0x014A	/* 5.2GHz OFDM power offset */
+ #define SSB_SPROM8_OFDM5GHPO		0x014E	/* 5.8GHz OFDM power offset */
+ 
++#define SSB_SPROM8_2G_MCSPO		0x0152
++#define SSB_SPROM8_5G_MCSPO		0x0162
++#define SSB_SPROM8_5GL_MCSPO		0x0172
++#define SSB_SPROM8_5GH_MCSPO		0x0182
++
++#define SSB_SPROM8_CDDPO		0x0192
++#define SSB_SPROM8_STBCPO		0x0194
++#define SSB_SPROM8_BW40PO		0x0196
++#define SSB_SPROM8_BWDUPPO		0x0198
++
+ /* Values for boardflags_lo read from SPROM */
+ #define SSB_BFL_BTCOEXIST		0x0001	/* implements Bluetooth coexistance */
+ #define SSB_BFL_PACTRL			0x0002	/* GPIO 9 controlling the PA */
diff --git a/target/linux/generic/patches-3.3/021-ssb_add_pci_id.patch b/target/linux/generic/patches-3.3/021-ssb_add_pci_id.patch
deleted file mode 100644
index 7cffebec48..0000000000
--- a/target/linux/generic/patches-3.3/021-ssb_add_pci_id.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/drivers/ssb/b43_pci_bridge.c
-+++ b/drivers/ssb/b43_pci_bridge.c
-@@ -29,6 +29,8 @@ static const struct pci_device_id b43_pc
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4322) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43222) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) },
diff --git a/target/linux/generic/patches-3.3/025-bcma_backport.patch b/target/linux/generic/patches-3.3/025-bcma_backport.patch
index 7117fbaf15..3fb7a564fa 100644
--- a/target/linux/generic/patches-3.3/025-bcma_backport.patch
+++ b/target/linux/generic/patches-3.3/025-bcma_backport.patch
@@ -34,6 +34,25 @@
  #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
  
  #endif
+--- a/drivers/bcma/core.c
++++ b/drivers/bcma/core.c
+@@ -30,6 +30,7 @@ void bcma_core_disable(struct bcma_devic
+ 	udelay(10);
+ 
+ 	bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
++	bcma_aread32(core, BCMA_RESET_CTL);
+ 	udelay(1);
+ }
+ EXPORT_SYMBOL_GPL(bcma_core_disable);
+@@ -77,7 +78,7 @@ void bcma_core_set_clockmode(struct bcma
+ 			pr_err("HT force timeout\n");
+ 		break;
+ 	case BCMA_CLKMODE_DYNAMIC:
+-		pr_warn("Dynamic clockmode not supported yet!\n");
++		bcma_set32(core, BCMA_CLKCTLST, ~BCMA_CLKCTLST_FORCEHT);
+ 		break;
+ 	}
+ }
 --- a/drivers/bcma/driver_chipcommon_pmu.c
 +++ b/drivers/bcma/driver_chipcommon_pmu.c
 @@ -80,6 +80,7 @@ static void bcma_pmu_resources_init(stru
@@ -57,7 +76,7 @@
   *
   * Licensed under the GNU/GPL. See COPYING for details.
   */
-@@ -16,40 +17,41 @@
+@@ -16,40 +17,39 @@
   * R/W ops.
   **************************************************/
  
@@ -72,7 +91,7 @@
 +	return pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_DATA);
  }
  
- #if 0
+-#if 0
  static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data)
  {
 -	pcicore_write32(pc, 0x130, address);
@@ -82,7 +101,7 @@
 +	pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR);
 +	pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_DATA, data);
  }
- #endif
+-#endif
  
  static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy)
  {
@@ -115,7 +134,7 @@
  			break;
  		msleep(1);
  	}
-@@ -57,79 +59,84 @@ static void bcma_pcie_mdio_set_phy(struc
+@@ -57,79 +57,84 @@ static void bcma_pcie_mdio_set_phy(struc
  
  static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address)
  {
@@ -231,7 +250,7 @@
  }
  
  /**************************************************
-@@ -138,72 +145,53 @@ static void bcma_pcie_mdio_write(struct
+@@ -138,72 +143,90 @@ static void bcma_pcie_mdio_write(struct
  
  static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc)
  {
@@ -266,6 +285,41 @@
 +		bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL,
 +		                     BCMA_CORE_PCI_SERDES_PLL_CTRL,
 +		                     tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN);
++}
++
++static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc)
++{
++	struct bcma_device *core = pc->core;
++	u16 val16, core_index;
++	uint regoff;
++
++	regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_PI_OFFSET);
++	core_index = (u16)core->core_index;
++
++	val16 = pcicore_read16(pc, regoff);
++	if (((val16 & BCMA_CORE_PCI_SPROM_PI_MASK) >> BCMA_CORE_PCI_SPROM_PI_SHIFT)
++	     != core_index) {
++		val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) |
++			(val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK);
++		pcicore_write16(pc, regoff, val16);
++	}
++}
++
++/* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */
++/* Needs to happen when coming out of 'standby'/'hibernate' */
++static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc)
++{
++	u16 val16;
++	uint regoff;
++
++	regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_MISC_CONFIG);
++
++	val16 = pcicore_read16(pc, regoff);
++
++	if (!(val16 & BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST)) {
++		val16 |= BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST;
++		pcicore_write16(pc, regoff, val16);
++	}
  }
  
  /**************************************************
@@ -275,7 +329,9 @@
 -static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
 +static void __devinit bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
  {
++	bcma_core_pci_fixcfg(pc);
  	bcma_pcicore_serdes_workaround(pc);
++	bcma_core_pci_config_fixup(pc);
  }
  
 -static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
@@ -327,6 +383,24 @@
  }
  
  int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
+@@ -236,3 +259,17 @@ out:
+ 	return err;
+ }
+ EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
++
++void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend)
++{
++	u32 w;
++
++	w = bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG);
++	if (extend)
++		w |= BCMA_CORE_PCI_ASPMTIMER_EXTEND;
++	else
++		w &= ~BCMA_CORE_PCI_ASPMTIMER_EXTEND;
++	bcma_pcie_write(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG, w);
++	bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG);
++}
++EXPORT_SYMBOL_GPL(bcma_core_pci_extend_L1timer);
 --- a/drivers/bcma/driver_pci_host.c
 +++ b/drivers/bcma/driver_pci_host.c
 @@ -2,13 +2,588 @@
@@ -452,7 +526,7 @@
 +		if (unlikely(!addr))
 +			goto out;
 +		err = -ENOMEM;
-+		mmio = ioremap_nocache(addr, len);
++		mmio = ioremap_nocache(addr, sizeof(val));
 +		if (!mmio)
 +			goto out;
 +
@@ -504,7 +578,7 @@
 +			addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0;
 +			addr |= (func << 8);
 +			addr |= (off & 0xfc);
-+			mmio = ioremap_nocache(addr, len);
++			mmio = ioremap_nocache(addr, sizeof(val));
 +			if (!mmio)
 +				goto out;
 +		}
@@ -513,7 +587,7 @@
 +		if (unlikely(!addr))
 +			goto out;
 +		err = -ENOMEM;
-+		mmio = ioremap_nocache(addr, len);
++		mmio = ioremap_nocache(addr, sizeof(val));
 +		if (!mmio)
 +			goto out;
 +
@@ -824,8 +898,8 @@
 +	/* Ok, ready to run, register it to the system.
 +	 * The following needs change, if we want to port hostmode
 +	 * to non-MIPS platform. */
-+	io_map_base = (unsigned long)ioremap_nocache(BCMA_SOC_PCI_MEM,
-+						     0x04000000);
++	io_map_base = (unsigned long)ioremap_nocache(pc_host->mem_resource.start,
++						     resource_size(&pc_host->mem_resource));
 +	pc_host->pci_controller.io_map_base = io_map_base;
 +	set_io_port_base(pc_host->pci_controller.io_map_base);
 +	/* Give some time to the PCI controller to configure itself with the new
@@ -933,6 +1007,34 @@
  {
  	struct bcma_bus *bus;
  	int err = -ENOMEM;
+@@ -201,6 +201,9 @@ static int bcma_host_pci_probe(struct pc
+ 	bus->hosttype = BCMA_HOSTTYPE_PCI;
+ 	bus->ops = &bcma_host_pci_ops;
+ 
++	bus->boardinfo.vendor = bus->host_pci->subsystem_vendor;
++	bus->boardinfo.type = bus->host_pci->subsystem_device;
++
+ 	/* Register */
+ 	err = bcma_bus_register(bus);
+ 	if (err)
+@@ -222,7 +225,7 @@ err_kfree_bus:
+ 	return err;
+ }
+ 
+-static void bcma_host_pci_remove(struct pci_dev *dev)
++static void __devexit bcma_host_pci_remove(struct pci_dev *dev)
+ {
+ 	struct bcma_bus *bus = pci_get_drvdata(dev);
+ 
+@@ -277,7 +280,7 @@ static struct pci_driver bcma_pci_bridge
+ 	.name = "bcma-pci-bridge",
+ 	.id_table = bcma_pci_bridge_tbl,
+ 	.probe = bcma_host_pci_probe,
+-	.remove = bcma_host_pci_remove,
++	.remove = __devexit_p(bcma_host_pci_remove),
+ 	.driver.pm = BCMA_PM_OPS,
+ };
+ 
 --- a/drivers/bcma/main.c
 +++ b/drivers/bcma/main.c
 @@ -13,6 +13,12 @@
@@ -993,7 +1095,104 @@
  	if (err) {
 --- a/drivers/bcma/scan.c
 +++ b/drivers/bcma/scan.c
-@@ -212,6 +212,17 @@ static struct bcma_device *bcma_find_cor
+@@ -19,7 +19,14 @@ struct bcma_device_id_name {
+ 	u16 id;
+ 	const char *name;
+ };
+-struct bcma_device_id_name bcma_device_names[] = {
++
++static const struct bcma_device_id_name bcma_arm_device_names[] = {
++	{ BCMA_CORE_ARM_1176, "ARM 1176" },
++	{ BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },
++	{ BCMA_CORE_ARM_CM3, "ARM CM3" },
++};
++
++static const struct bcma_device_id_name bcma_bcm_device_names[] = {
+ 	{ BCMA_CORE_OOB_ROUTER, "OOB Router" },
+ 	{ BCMA_CORE_INVALID, "Invalid" },
+ 	{ BCMA_CORE_CHIPCOMMON, "ChipCommon" },
+@@ -27,7 +34,6 @@ struct bcma_device_id_name bcma_device_n
+ 	{ BCMA_CORE_SRAM, "SRAM" },
+ 	{ BCMA_CORE_SDRAM, "SDRAM" },
+ 	{ BCMA_CORE_PCI, "PCI" },
+-	{ BCMA_CORE_MIPS, "MIPS" },
+ 	{ BCMA_CORE_ETHERNET, "Fast Ethernet" },
+ 	{ BCMA_CORE_V90, "V90" },
+ 	{ BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" },
+@@ -44,7 +50,6 @@ struct bcma_device_id_name bcma_device_n
+ 	{ BCMA_CORE_PHY_A, "PHY A" },
+ 	{ BCMA_CORE_PHY_B, "PHY B" },
+ 	{ BCMA_CORE_PHY_G, "PHY G" },
+-	{ BCMA_CORE_MIPS_3302, "MIPS 3302" },
+ 	{ BCMA_CORE_USB11_HOST, "USB 1.1 Host" },
+ 	{ BCMA_CORE_USB11_DEV, "USB 1.1 Device" },
+ 	{ BCMA_CORE_USB20_HOST, "USB 2.0 Host" },
+@@ -58,15 +63,11 @@ struct bcma_device_id_name bcma_device_n
+ 	{ BCMA_CORE_PHY_N, "PHY N" },
+ 	{ BCMA_CORE_SRAM_CTL, "SRAM Controller" },
+ 	{ BCMA_CORE_MINI_MACPHY, "Mini MACPHY" },
+-	{ BCMA_CORE_ARM_1176, "ARM 1176" },
+-	{ BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },
+ 	{ BCMA_CORE_PHY_LP, "PHY LP" },
+ 	{ BCMA_CORE_PMU, "PMU" },
+ 	{ BCMA_CORE_PHY_SSN, "PHY SSN" },
+ 	{ BCMA_CORE_SDIO_DEV, "SDIO Device" },
+-	{ BCMA_CORE_ARM_CM3, "ARM CM3" },
+ 	{ BCMA_CORE_PHY_HT, "PHY HT" },
+-	{ BCMA_CORE_MIPS_74K, "MIPS 74K" },
+ 	{ BCMA_CORE_MAC_GBIT, "GBit MAC" },
+ 	{ BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" },
+ 	{ BCMA_CORE_PCIE_RC, "PCIe Root Complex" },
+@@ -79,16 +80,41 @@ struct bcma_device_id_name bcma_device_n
+ 	{ BCMA_CORE_SHIM, "SHIM" },
+ 	{ BCMA_CORE_DEFAULT, "Default" },
+ };
+-const char *bcma_device_name(struct bcma_device_id *id)
++
++static const struct bcma_device_id_name bcma_mips_device_names[] = {
++	{ BCMA_CORE_MIPS, "MIPS" },
++	{ BCMA_CORE_MIPS_3302, "MIPS 3302" },
++	{ BCMA_CORE_MIPS_74K, "MIPS 74K" },
++};
++
++static const char *bcma_device_name(const struct bcma_device_id *id)
+ {
+-	int i;
++	const struct bcma_device_id_name *names;
++	int size, i;
+ 
+-	if (id->manuf == BCMA_MANUF_BCM) {
+-		for (i = 0; i < ARRAY_SIZE(bcma_device_names); i++) {
+-			if (bcma_device_names[i].id == id->id)
+-				return bcma_device_names[i].name;
+-		}
++	/* search manufacturer specific names */
++	switch (id->manuf) {
++	case BCMA_MANUF_ARM:
++		names = bcma_arm_device_names;
++		size = ARRAY_SIZE(bcma_arm_device_names);
++		break;
++	case BCMA_MANUF_BCM:
++		names = bcma_bcm_device_names;
++		size = ARRAY_SIZE(bcma_bcm_device_names);
++		break;
++	case BCMA_MANUF_MIPS:
++		names = bcma_mips_device_names;
++		size = ARRAY_SIZE(bcma_mips_device_names);
++		break;
++	default:
++		return "UNKNOWN";
++	}
++
++	for (i = 0; i < size; i++) {
++		if (names[i].id == id->id)
++			return names[i].name;
+ 	}
++
+ 	return "UNKNOWN";
+ }
+ 
+@@ -212,6 +238,17 @@ static struct bcma_device *bcma_find_cor
  	return NULL;
  }
  
@@ -1011,7 +1210,7 @@
  static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
  			      struct bcma_device_id *match, int core_num,
  			      struct bcma_device *core)
-@@ -353,6 +364,7 @@ static int bcma_get_next_core(struct bcm
+@@ -353,6 +390,7 @@ static int bcma_get_next_core(struct bcm
  void bcma_init_bus(struct bcma_bus *bus)
  {
  	s32 tmp;
@@ -1019,7 +1218,7 @@
  
  	if (bus->init_done)
  		return;
-@@ -363,9 +375,12 @@ void bcma_init_bus(struct bcma_bus *bus)
+@@ -363,9 +401,12 @@ void bcma_init_bus(struct bcma_bus *bus)
  	bcma_scan_switch_core(bus, BCMA_ADDR_BASE);
  
  	tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID);
@@ -1035,7 +1234,7 @@
  	bus->init_done = true;
  }
  
-@@ -392,6 +407,7 @@ int bcma_bus_scan(struct bcma_bus *bus)
+@@ -392,6 +433,7 @@ int bcma_bus_scan(struct bcma_bus *bus)
  	bcma_scan_switch_core(bus, erombase);
  
  	while (eromptr < eromend) {
@@ -1043,7 +1242,7 @@
  		struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL);
  		if (!core)
  			return -ENOMEM;
-@@ -414,6 +430,8 @@ int bcma_bus_scan(struct bcma_bus *bus)
+@@ -414,6 +456,8 @@ int bcma_bus_scan(struct bcma_bus *bus)
  
  		core->core_index = core_num++;
  		bus->nr_cores++;
@@ -1122,7 +1321,7 @@
  
  /**************************************************
   * R/W ops.
-@@ -124,10 +176,21 @@ static int bcma_sprom_valid(const u16 *s
+@@ -124,10 +176,37 @@ static int bcma_sprom_valid(const u16 *s
   * SPROM extraction.
   **************************************************/
  
@@ -1130,6 +1329,22 @@
 +
 +#define SPEX(_field, _offset, _mask, _shift)	\
 +	bus->sprom._field = ((sprom[SPOFF(_offset)] & (_mask)) >> (_shift))
++
++#define SPEX32(_field, _offset, _mask, _shift)	\
++	bus->sprom._field = ((((u32)sprom[SPOFF((_offset)+2)] << 16 | \
++				sprom[SPOFF(_offset)]) & (_mask)) >> (_shift))
++
++#define SPEX_ARRAY8(_field, _offset, _mask, _shift)	\
++	do {	\
++		SPEX(_field[0], _offset +  0, _mask, _shift);	\
++		SPEX(_field[1], _offset +  2, _mask, _shift);	\
++		SPEX(_field[2], _offset +  4, _mask, _shift);	\
++		SPEX(_field[3], _offset +  6, _mask, _shift);	\
++		SPEX(_field[4], _offset +  8, _mask, _shift);	\
++		SPEX(_field[5], _offset + 10, _mask, _shift);	\
++		SPEX(_field[6], _offset + 12, _mask, _shift);	\
++		SPEX(_field[7], _offset + 14, _mask, _shift);	\
++	} while (0)
 +
  static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
  {
@@ -1145,7 +1360,7 @@
  
  	bus->sprom.revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] &
  		SSB_SPROM_REVISION_REV;
-@@ -137,85 +200,229 @@ static void bcma_sprom_extract_r8(struct
+@@ -137,85 +216,363 @@ static void bcma_sprom_extract_r8(struct
  		*(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
  	}
  
@@ -1257,7 +1472,8 @@
 +	SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, ~0, 0);
 +	SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, ~0, 0);
 +
-+	SPEX(country_code, SSB_SPROM8_CCODE, ~0, 0);
++	SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
++	SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
 +
 +	/* Extract cores power info info */
 +	for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
@@ -1312,6 +1528,136 @@
 +	     SSB_SROM8_FEM_TR_ISO_SHIFT);
 +	SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT,
 +	     SSB_SROM8_FEM_ANTSWLUT_SHIFT);
++
++	SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
++	     SSB_SPROM8_ANTAVAIL_A_SHIFT);
++	SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
++	     SSB_SPROM8_ANTAVAIL_BG_SHIFT);
++	SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
++	SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
++	     SSB_SPROM8_ITSSI_BG_SHIFT);
++	SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
++	SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
++	     SSB_SPROM8_ITSSI_A_SHIFT);
++	SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
++	SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
++	     SSB_SPROM8_MAXP_AL_SHIFT);
++	SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
++	SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
++	     SSB_SPROM8_GPIOA_P1_SHIFT);
++	SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
++	SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
++	     SSB_SPROM8_GPIOB_P3_SHIFT);
++	SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
++	SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
++	     SSB_SPROM8_TRI5G_SHIFT);
++	SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
++	SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
++	     SSB_SPROM8_TRI5GH_SHIFT);
++	SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G,
++	     SSB_SPROM8_RXPO2G_SHIFT);
++	SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
++	     SSB_SPROM8_RXPO5G_SHIFT);
++	SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
++	SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
++	     SSB_SPROM8_RSSISMC2G_SHIFT);
++	SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
++	     SSB_SPROM8_RSSISAV2G_SHIFT);
++	SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
++	     SSB_SPROM8_BXA2G_SHIFT);
++	SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
++	SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
++	     SSB_SPROM8_RSSISMC5G_SHIFT);
++	SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
++	     SSB_SPROM8_RSSISAV5G_SHIFT);
++	SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
++	     SSB_SPROM8_BXA5G_SHIFT);
++
++	SPEX(pa0b0, SSB_SPROM8_PA0B0, ~0, 0);
++	SPEX(pa0b1, SSB_SPROM8_PA0B1, ~0, 0);
++	SPEX(pa0b2, SSB_SPROM8_PA0B2, ~0, 0);
++	SPEX(pa1b0, SSB_SPROM8_PA1B0, ~0, 0);
++	SPEX(pa1b1, SSB_SPROM8_PA1B1, ~0, 0);
++	SPEX(pa1b2, SSB_SPROM8_PA1B2, ~0, 0);
++	SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, ~0, 0);
++	SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, ~0, 0);
++	SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, ~0, 0);
++	SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, ~0, 0);
++	SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, ~0, 0);
++	SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, ~0, 0);
++	SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, ~0, 0);
++	SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, ~0, 0);
++	SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, ~0, 0);
++	SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, ~0, 0);
++	SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0);
++
++	/* Extract the antenna gain values. */
++	SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
++	     SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
++	SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
++	     SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
++	SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
++	     SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
++	SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
++	     SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
++
++	SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
++	     SSB_SPROM8_LEDDC_ON_SHIFT);
++	SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
++	     SSB_SPROM8_LEDDC_OFF_SHIFT);
++
++	SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
++	     SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
++	SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
++	     SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
++	SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
++	     SSB_SPROM8_TXRXC_SWITCH_SHIFT);
++
++	SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
++
++	SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
++	SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
++
++	SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
++	     SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
++	SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
++	     SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
++	SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
++	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
++	SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
++	SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
++	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
++	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
++	SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
++	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
++	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
++	SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
++	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
++	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
++	SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
++	     SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
++
++	SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
++	SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
++	SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
++	SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
++
++	SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
++	     SSB_SPROM8_THERMAL_TRESH_SHIFT);
++	SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
++	     SSB_SPROM8_THERMAL_OFFSET_SHIFT);
++	SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
++	     SSB_SPROM8_TEMPDELTA_PHYCAL,
++	     SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
++	SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
++	     SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
++	SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
++	     SSB_SPROM8_TEMPDELTA_HYSTERESIS,
++	     SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
 +}
 +
 +/*
@@ -1421,16 +1767,19 @@
 -	if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
 -		return -ENOENT;
 +	if (!bcma_sprom_ext_available(bus)) {
++		bool sprom_onchip;
++
 +		/*
 +		 * External SPROM takes precedence so check
 +		 * on-chip OTP only when no external SPROM
 +		 * is present.
 +		 */
-+		if (bcma_sprom_onchip_available(bus)) {
++		sprom_onchip = bcma_sprom_onchip_available(bus);
++		if (sprom_onchip) {
 +			/* determine offset */
 +			offset = bcma_sprom_onchip_offset(bus);
 +		}
-+		if (!offset) {
++		if (!offset || !sprom_onchip) {
 +			/*
 +			 * Maybe there is no SPROM on the device?
 +			 * Now we ask the arch code if there is some sprom
@@ -1443,7 +1792,7 @@
  
  	sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
  			GFP_KERNEL);
-@@ -225,11 +432,7 @@ int bcma_sprom_get(struct bcma_bus *bus)
+@@ -225,11 +582,7 @@ int bcma_sprom_get(struct bcma_bus *bus)
  	if (bus->chipinfo.id == 0x4331)
  		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
  
@@ -1458,7 +1807,19 @@
  	if (bus->chipinfo.id == 0x4331)
 --- a/include/linux/bcma/bcma.h
 +++ b/include/linux/bcma/bcma.h
-@@ -136,6 +136,7 @@ struct bcma_device {
+@@ -26,6 +26,11 @@ struct bcma_chipinfo {
+ 	u8 pkg;
+ };
+ 
++struct bcma_boardinfo {
++	u16 vendor;
++	u16 type;
++};
++
+ enum bcma_clkmode {
+ 	BCMA_CLKMODE_FAST,
+ 	BCMA_CLKMODE_DYNAMIC,
+@@ -136,6 +141,7 @@ struct bcma_device {
  	bool dev_registered;
  
  	u8 core_index;
@@ -1466,7 +1827,7 @@
  
  	u32 addr;
  	u32 wrap;
-@@ -175,6 +176,12 @@ int __bcma_driver_register(struct bcma_d
+@@ -175,6 +181,12 @@ int __bcma_driver_register(struct bcma_d
  
  extern void bcma_driver_unregister(struct bcma_driver *drv);
  
@@ -1479,7 +1840,13 @@
  struct bcma_bus {
  	/* The MMIO area. */
  	void __iomem *mmio;
-@@ -195,6 +202,7 @@ struct bcma_bus {
+@@ -191,10 +203,13 @@ struct bcma_bus {
+ 
+ 	struct bcma_chipinfo chipinfo;
+ 
++	struct bcma_boardinfo boardinfo;
++
+ 	struct bcma_device *mapped_core;
  	struct list_head cores;
  	u8 nr_cores;
  	u8 init_done:1;
@@ -1487,7 +1854,7 @@
  
  	struct bcma_drv_cc drv_cc;
  	struct bcma_drv_pci drv_pci;
-@@ -282,6 +290,7 @@ static inline void bcma_maskset16(struct
+@@ -282,6 +297,7 @@ static inline void bcma_maskset16(struct
  	bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set);
  }
  
@@ -1560,7 +1927,7 @@
  #define BCMA_CC_PMU5_MAINPLL_CPU	1
 --- a/include/linux/bcma/bcma_driver_pci.h
 +++ b/include/linux/bcma/bcma_driver_pci.h
-@@ -53,6 +53,35 @@ struct pci_dev;
+@@ -53,11 +53,47 @@ struct pci_dev;
  #define  BCMA_CORE_PCI_SBTOPCI1_MASK		0xFC000000
  #define BCMA_CORE_PCI_SBTOPCI2			0x0108	/* Backplane to PCI translation 2 (sbtopci2) */
  #define  BCMA_CORE_PCI_SBTOPCI2_MASK		0xC0000000
@@ -1596,7 +1963,19 @@
  #define BCMA_CORE_PCI_PCICFG0			0x0400	/* PCI config space 0 (rev >= 8) */
  #define BCMA_CORE_PCI_PCICFG1			0x0500	/* PCI config space 1 (rev >= 8) */
  #define BCMA_CORE_PCI_PCICFG2			0x0600	/* PCI config space 2 (rev >= 8) */
-@@ -72,20 +101,114 @@ struct pci_dev;
+ #define BCMA_CORE_PCI_PCICFG3			0x0700	/* PCI config space 3 (rev >= 8) */
+ #define BCMA_CORE_PCI_SPROM(wordoffset)		(0x0800 + ((wordoffset) * 2)) /* SPROM shadow area (72 bytes) */
++#define  BCMA_CORE_PCI_SPROM_PI_OFFSET		0	/* first word */
++#define   BCMA_CORE_PCI_SPROM_PI_MASK		0xf000	/* bit 15:12 */
++#define   BCMA_CORE_PCI_SPROM_PI_SHIFT		12	/* bit 15:12 */
++#define  BCMA_CORE_PCI_SPROM_MISC_CONFIG	5	/* word 5 */
++#define   BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST	0x8000	/* bit 15 */
++#define   BCMA_CORE_PCI_SPROM_CLKREQ_OFFSET_REV5	20	/* word 20 for srom rev <= 5 */
++#define   BCMA_CORE_PCI_SPROM_CLKREQ_ENB	0x0800	/* bit 11 */
+ 
+ /* SBtoPCIx */
+ #define BCMA_CORE_PCI_SBTOPCI_MEM		0x00000000
+@@ -72,20 +108,118 @@ struct pci_dev;
  #define  BCMA_CORE_PCI_SBTOPCI_RC_READL		0x00000010 /* Memory read line */
  #define  BCMA_CORE_PCI_SBTOPCI_RC_READM		0x00000020 /* Memory read multiple */
  
@@ -1632,6 +2011,7 @@
 +#define BCMA_CORE_PCI_DLLP_LRREG		0x120	/* Link Replay */
 +#define BCMA_CORE_PCI_DLLP_LACKTOREG		0x124	/* Link Ack Timeout */
 +#define BCMA_CORE_PCI_DLLP_PMTHRESHREG		0x128	/* Power Management Threshold */
++#define  BCMA_CORE_PCI_ASPMTIMER_EXTEND		0x01000000 /* > rev7: enable extend ASPM timer */
 +#define BCMA_CORE_PCI_DLLP_RTRYWPREG		0x12C	/* Retry buffer write ptr */
 +#define BCMA_CORE_PCI_DLLP_RTRYRPREG		0x130	/* Retry buffer Read ptr */
 +#define BCMA_CORE_PCI_DLLP_RTRYPPREG		0x134	/* Retry buffer Purged ptr */
@@ -1700,17 +2080,20 @@
  };
  
  /* Register access */
++#define pcicore_read16(pc, offset)		bcma_read16((pc)->core, offset)
  #define pcicore_read32(pc, offset)		bcma_read32((pc)->core, offset)
++#define pcicore_write16(pc, offset, val)	bcma_write16((pc)->core, offset, val)
  #define pcicore_write32(pc, offset, val)	bcma_write32((pc)->core, offset, val)
  
 -extern void bcma_core_pci_init(struct bcma_drv_pci *pc);
 +extern void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc);
  extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
  				 struct bcma_device *core, bool enable);
- 
++extern void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend);
++
 +extern int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev);
 +extern int bcma_core_pci_plat_dev_init(struct pci_dev *dev);
-+
+ 
  #endif /* LINUX_BCMA_DRIVER_PCI_H_ */
 --- a/include/linux/bcma/bcma_regs.h
 +++ b/include/linux/bcma/bcma_regs.h
-- 
GitLab