--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -90,6 +90,12 @@ config B43_SDIO
 
 #Data transfers to the device via PIO. We want it as a fallback even
 # if we can do DMA.
+config B43_BCMA_PIO
+	bool
+	depends on B43_BCMA
+	select BCMA_BLOCKIO
+	default y
+
 config B43_PIO
 	bool
 	depends on B43
@@ -125,6 +131,14 @@ config B43_PHY_HT
 
 	  Say N, this is BROKEN and crashes driver.
 
+config B43_PHY_LCN
+	bool "Support for LCN-PHY devices (BROKEN)"
+	depends on B43 && BROKEN
+	---help---
+	  Support for the LCN-PHY.
+
+	  Say N, this is BROKEN and crashes driver.
+
 # This config option automatically enables b43 LEDS support,
 # if it's possible.
 config B43_LEDS
--- a/drivers/net/wireless/b43/Makefile
+++ b/drivers/net/wireless/b43/Makefile
@@ -11,7 +11,9 @@ b43-$(CONFIG_B43_PHY_N)		+= phy_n.o
 b43-$(CONFIG_B43_PHY_LP)	+= phy_lp.o
 b43-$(CONFIG_B43_PHY_LP)	+= tables_lpphy.o
 b43-$(CONFIG_B43_PHY_HT)	+= phy_ht.o
+b43-$(CONFIG_B43_PHY_HT)	+= tables_phy_ht.o
 b43-$(CONFIG_B43_PHY_HT)	+= radio_2059.o
+b43-$(CONFIG_B43_PHY_LCN)	+= phy_lcn.o tables_phy_lcn.o
 b43-y				+= sysfs.o
 b43-y				+= xmit.o
 b43-y				+= lo.o
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -433,6 +433,12 @@ enum {
 #define  B43_BCMA_IOCTL_PHY_BW_40MHZ	0x00000080	/* 40 MHz bandwidth, 160 MHz PHY */
 #define B43_BCMA_IOCTL_GMODE		0x00002000	/* G Mode Enable */
 
+/* BCMA 802.11 core specific IO status (BCMA_IOST) flags */
+#define B43_BCMA_IOST_2G_PHY		0x00000001	/* 2.4G capable phy */
+#define B43_BCMA_IOST_5G_PHY		0x00000002	/* 5G capable phy */
+#define B43_BCMA_IOST_FASTCLKA		0x00000004	/* Fast Clock Available */
+#define B43_BCMA_IOST_DUALB_PHY		0x00000008	/* Dualband phy */
+
 /* 802.11 core specific TM State Low (SSB_TMSLOW) flags */
 #define B43_TMSLOW_GMODE		0x20000000	/* G Mode Enable */
 #define B43_TMSLOW_PHY_BANDWIDTH	0x00C00000	/* PHY band width and clock speed mask (N-PHY only) */
@@ -588,6 +594,7 @@ struct b43_dma {
 	struct b43_dmaring *rx_ring;
 
 	u32 translation; /* Routing bits */
+	bool parity; /* Check for parity */
 };
 
 struct b43_pio_txqueue;
@@ -726,7 +733,6 @@ enum {
 
 /* Data structure for one wireless device (802.11 core) */
 struct b43_wldev {
-	struct ssb_device *sdev; /* TODO: remove when b43_bus_dev is ready */
 	struct b43_bus_dev *dev;
 	struct b43_wl *wl;
 
--- a/drivers/net/wireless/b43/bus.c
+++ b/drivers/net/wireless/b43/bus.c
@@ -23,58 +23,155 @@
 #include "b43.h"
 #include "bus.h"
 
+/* BCMA */
+#ifdef CONFIG_B43_BCMA
+static int b43_bus_bcma_bus_may_powerdown(struct b43_bus_dev *dev)
+{
+	return 0; /* bcma_bus_may_powerdown(dev->bdev->bus); */
+}
+static int b43_bus_bcma_bus_powerup(struct b43_bus_dev *dev,
+					  bool dynamic_pctl)
+{
+	return 0; /* bcma_bus_powerup(dev->sdev->bus, dynamic_pctl); */
+}
+static int b43_bus_bcma_device_is_enabled(struct b43_bus_dev *dev)
+{
+	return bcma_core_is_enabled(dev->bdev);
+}
+static void b43_bus_bcma_device_enable(struct b43_bus_dev *dev,
+					     u32 core_specific_flags)
+{
+	bcma_core_enable(dev->bdev, core_specific_flags);
+}
+static void b43_bus_bcma_device_disable(struct b43_bus_dev *dev,
+					      u32 core_specific_flags)
+{
+	bcma_core_disable(dev->bdev, core_specific_flags);
+}
+static u16 b43_bus_bcma_read16(struct b43_bus_dev *dev, u16 offset)
+{
+	return bcma_read16(dev->bdev, offset);
+}
+static u32 b43_bus_bcma_read32(struct b43_bus_dev *dev, u16 offset)
+{
+	return bcma_read32(dev->bdev, offset);
+}
+static
+void b43_bus_bcma_write16(struct b43_bus_dev *dev, u16 offset, u16 value)
+{
+	bcma_write16(dev->bdev, offset, value);
+}
+static
+void b43_bus_bcma_write32(struct b43_bus_dev *dev, u16 offset, u32 value)
+{
+	bcma_write32(dev->bdev, offset, value);
+}
+static
+void b43_bus_bcma_block_read(struct b43_bus_dev *dev, void *buffer,
+			     size_t count, u16 offset, u8 reg_width)
+{
+	bcma_block_read(dev->bdev, buffer, count, offset, reg_width);
+}
+static
+void b43_bus_bcma_block_write(struct b43_bus_dev *dev, const void *buffer,
+			      size_t count, u16 offset, u8 reg_width)
+{
+	bcma_block_write(dev->bdev, buffer, count, offset, reg_width);
+}
+
+struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core)
+{
+	struct b43_bus_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	dev->bus_type = B43_BUS_BCMA;
+	dev->bdev = core;
+
+	dev->bus_may_powerdown = b43_bus_bcma_bus_may_powerdown;
+	dev->bus_powerup = b43_bus_bcma_bus_powerup;
+	dev->device_is_enabled = b43_bus_bcma_device_is_enabled;
+	dev->device_enable = b43_bus_bcma_device_enable;
+	dev->device_disable = b43_bus_bcma_device_disable;
+
+	dev->read16 = b43_bus_bcma_read16;
+	dev->read32 = b43_bus_bcma_read32;
+	dev->write16 = b43_bus_bcma_write16;
+	dev->write32 = b43_bus_bcma_write32;
+	dev->block_read = b43_bus_bcma_block_read;
+	dev->block_write = b43_bus_bcma_block_write;
+
+	dev->dev = &core->dev;
+	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->chip_id = core->bus->chipinfo.id;
+	dev->chip_rev = core->bus->chipinfo.rev;
+	dev->chip_pkg = core->bus->chipinfo.pkg;
+
+	dev->bus_sprom = &core->bus->sprom;
+
+	dev->core_id = core->id.id;
+	dev->core_rev = core->id.rev;
+
+	return dev;
+}
+#endif /* CONFIG_B43_BCMA */
 
 /* SSB */
 #ifdef CONFIG_B43_SSB
-static inline int b43_bus_ssb_bus_may_powerdown(struct b43_bus_dev *dev)
+static int b43_bus_ssb_bus_may_powerdown(struct b43_bus_dev *dev)
 {
 	return ssb_bus_may_powerdown(dev->sdev->bus);
 }
-static inline int b43_bus_ssb_bus_powerup(struct b43_bus_dev *dev,
+static int b43_bus_ssb_bus_powerup(struct b43_bus_dev *dev,
 					  bool dynamic_pctl)
 {
 	return ssb_bus_powerup(dev->sdev->bus, dynamic_pctl);
 }
-static inline int b43_bus_ssb_device_is_enabled(struct b43_bus_dev *dev)
+static int b43_bus_ssb_device_is_enabled(struct b43_bus_dev *dev)
 {
 	return ssb_device_is_enabled(dev->sdev);
 }
-static inline void b43_bus_ssb_device_enable(struct b43_bus_dev *dev,
+static void b43_bus_ssb_device_enable(struct b43_bus_dev *dev,
 					     u32 core_specific_flags)
 {
 	ssb_device_enable(dev->sdev, core_specific_flags);
 }
-static inline void b43_bus_ssb_device_disable(struct b43_bus_dev *dev,
+static void b43_bus_ssb_device_disable(struct b43_bus_dev *dev,
 					      u32 core_specific_flags)
 {
 	ssb_device_disable(dev->sdev, core_specific_flags);
 }
 
-static inline u16 b43_bus_ssb_read16(struct b43_bus_dev *dev, u16 offset)
+static u16 b43_bus_ssb_read16(struct b43_bus_dev *dev, u16 offset)
 {
 	return ssb_read16(dev->sdev, offset);
 }
-static inline u32 b43_bus_ssb_read32(struct b43_bus_dev *dev, u16 offset)
+static u32 b43_bus_ssb_read32(struct b43_bus_dev *dev, u16 offset)
 {
 	return ssb_read32(dev->sdev, offset);
 }
-static inline
-void b43_bus_ssb_write16(struct b43_bus_dev *dev, u16 offset, u16 value)
+static void b43_bus_ssb_write16(struct b43_bus_dev *dev, u16 offset, u16 value)
 {
 	ssb_write16(dev->sdev, offset, value);
 }
-static inline
-void b43_bus_ssb_write32(struct b43_bus_dev *dev, u16 offset, u32 value)
+static void b43_bus_ssb_write32(struct b43_bus_dev *dev, u16 offset, u32 value)
 {
 	ssb_write32(dev->sdev, offset, value);
 }
-static inline
-void b43_bus_ssb_block_read(struct b43_bus_dev *dev, void *buffer,
-			    size_t count, u16 offset, u8 reg_width)
+static void b43_bus_ssb_block_read(struct b43_bus_dev *dev, void *buffer,
+				   size_t count, u16 offset, u8 reg_width)
 {
 	ssb_block_read(dev->sdev, buffer, count, offset, reg_width);
 }
-static inline
+static
 void b43_bus_ssb_block_write(struct b43_bus_dev *dev, const void *buffer,
 			     size_t count, u16 offset, u8 reg_width)
 {
@@ -125,3 +222,32 @@ struct b43_bus_dev *b43_bus_dev_ssb_init
 	return dev;
 }
 #endif /* CONFIG_B43_SSB */
+
+void *b43_bus_get_wldev(struct b43_bus_dev *dev)
+{
+	switch (dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		return bcma_get_drvdata(dev->bdev);
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		return ssb_get_drvdata(dev->sdev);
+#endif
+	}
+	return NULL;
+}
+
+void b43_bus_set_wldev(struct b43_bus_dev *dev, void *wldev)
+{
+	switch (dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		bcma_set_drvdata(dev->bdev, wldev);
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		ssb_set_drvdata(dev->sdev, wldev);
+#endif
+	}
+}
--- a/drivers/net/wireless/b43/bus.h
+++ b/drivers/net/wireless/b43/bus.h
@@ -2,12 +2,16 @@
 #define B43_BUS_H_
 
 enum b43_bus_type {
+#ifdef CONFIG_B43_BCMA
+	B43_BUS_BCMA,
+#endif
 	B43_BUS_SSB,
 };
 
 struct b43_bus_dev {
 	enum b43_bus_type bus_type;
 	union {
+		struct bcma_device *bdev;
 		struct ssb_device *sdev;
 	};
 
@@ -57,6 +61,10 @@ static inline bool b43_bus_host_is_sdio(
 		dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO);
 }
 
+struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core);
 struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev);
 
+void *b43_bus_get_wldev(struct b43_bus_dev *dev);
+void b43_bus_set_wldev(struct b43_bus_dev *dev, void *data);
+
 #endif /* B43_BUS_H_ */
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -174,7 +174,7 @@ static void op64_fill_descriptor(struct 
 	addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
 	addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
 	    >> SSB_DMA_TRANSLATION_SHIFT;
-	addrhi |= (ring->dev->dma.translation << 1);
+	addrhi |= ring->dev->dma.translation;
 	if (slot == ring->nr_slots - 1)
 		ctl0 |= B43_DMA64_DCTL0_DTABLEEND;
 	if (start)
@@ -659,6 +659,7 @@ static int dmacontroller_setup(struct b4
 	u32 value;
 	u32 addrext;
 	u32 trans = ring->dev->dma.translation;
+	bool parity = ring->dev->dma.parity;
 
 	if (ring->tx) {
 		if (ring->type == B43_DMA_64BIT) {
@@ -669,13 +670,15 @@ static int dmacontroller_setup(struct b4
 			value = B43_DMA64_TXENABLE;
 			value |= (addrext << B43_DMA64_TXADDREXT_SHIFT)
 			    & B43_DMA64_TXADDREXT_MASK;
+			if (!parity)
+				value |= B43_DMA64_TXPARITYDISABLE;
 			b43_dma_write(ring, B43_DMA64_TXCTL, value);
 			b43_dma_write(ring, B43_DMA64_TXRINGLO,
 				      (ringbase & 0xFFFFFFFF));
 			b43_dma_write(ring, B43_DMA64_TXRINGHI,
 				      ((ringbase >> 32) &
 				       ~SSB_DMA_TRANSLATION_MASK)
-				      | (trans << 1));
+				      | trans);
 		} else {
 			u32 ringbase = (u32) (ring->dmabase);
 
@@ -684,6 +687,8 @@ static int dmacontroller_setup(struct b4
 			value = B43_DMA32_TXENABLE;
 			value |= (addrext << B43_DMA32_TXADDREXT_SHIFT)
 			    & B43_DMA32_TXADDREXT_MASK;
+			if (!parity)
+				value |= B43_DMA32_TXPARITYDISABLE;
 			b43_dma_write(ring, B43_DMA32_TXCTL, value);
 			b43_dma_write(ring, B43_DMA32_TXRING,
 				      (ringbase & ~SSB_DMA_TRANSLATION_MASK)
@@ -702,13 +707,15 @@ static int dmacontroller_setup(struct b4
 			value |= B43_DMA64_RXENABLE;
 			value |= (addrext << B43_DMA64_RXADDREXT_SHIFT)
 			    & B43_DMA64_RXADDREXT_MASK;
+			if (!parity)
+				value |= B43_DMA64_RXPARITYDISABLE;
 			b43_dma_write(ring, B43_DMA64_RXCTL, value);
 			b43_dma_write(ring, B43_DMA64_RXRINGLO,
 				      (ringbase & 0xFFFFFFFF));
 			b43_dma_write(ring, B43_DMA64_RXRINGHI,
 				      ((ringbase >> 32) &
 				       ~SSB_DMA_TRANSLATION_MASK)
-				      | (trans << 1));
+				      | trans);
 			b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots *
 				      sizeof(struct b43_dmadesc64));
 		} else {
@@ -720,6 +727,8 @@ static int dmacontroller_setup(struct b4
 			value |= B43_DMA32_RXENABLE;
 			value |= (addrext << B43_DMA32_RXADDREXT_SHIFT)
 			    & B43_DMA32_RXADDREXT_MASK;
+			if (!parity)
+				value |= B43_DMA32_RXPARITYDISABLE;
 			b43_dma_write(ring, B43_DMA32_RXCTL, value);
 			b43_dma_write(ring, B43_DMA32_RXRING,
 				      (ringbase & ~SSB_DMA_TRANSLATION_MASK)
@@ -1055,7 +1064,26 @@ int b43_dma_init(struct b43_wldev *dev)
 	err = b43_dma_set_mask(dev, dmamask);
 	if (err)
 		return err;
-	dma->translation = ssb_dma_translation(dev->sdev);
+
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		dma->translation = bcma_core_dma_translation(dev->dev->bdev);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		dma->translation = ssb_dma_translation(dev->dev->sdev);
+		break;
+#endif
+	}
+
+	dma->parity = true;
+#ifdef CONFIG_B43_BCMA
+	/* TODO: find out which SSB devices need disabling parity */
+	if (dev->dev->bus_type == B43_BUS_BCMA)
+		dma->parity = false;
+#endif
 
 	err = -ENOMEM;
 	/* setup TX DMA channels. */
@@ -1600,6 +1628,7 @@ void b43_dma_rx(struct b43_dmaring *ring
 		dma_rx(ring, &slot);
 		update_max_used_slots(ring, ++used_slots);
 	}
+	wmb();
 	ops->set_current_rxslot(ring, slot);
 	ring->current_slot = slot;
 }
--- a/drivers/net/wireless/b43/dma.h
+++ b/drivers/net/wireless/b43/dma.h
@@ -20,6 +20,7 @@
 #define		B43_DMA32_TXSUSPEND			0x00000002
 #define		B43_DMA32_TXLOOPBACK		0x00000004
 #define		B43_DMA32_TXFLUSH			0x00000010
+#define		B43_DMA32_TXPARITYDISABLE		0x00000800
 #define		B43_DMA32_TXADDREXT_MASK		0x00030000
 #define		B43_DMA32_TXADDREXT_SHIFT		16
 #define B43_DMA32_TXRING				0x04
@@ -44,6 +45,7 @@
 #define		B43_DMA32_RXFROFF_MASK		0x000000FE
 #define		B43_DMA32_RXFROFF_SHIFT		1
 #define		B43_DMA32_RXDIRECTFIFO		0x00000100
+#define		B43_DMA32_RXPARITYDISABLE		0x00000800
 #define		B43_DMA32_RXADDREXT_MASK		0x00030000
 #define		B43_DMA32_RXADDREXT_SHIFT		16
 #define B43_DMA32_RXRING				0x14
@@ -84,6 +86,7 @@ struct b43_dmadesc32 {
 #define		B43_DMA64_TXSUSPEND			0x00000002
 #define		B43_DMA64_TXLOOPBACK		0x00000004
 #define		B43_DMA64_TXFLUSH			0x00000010
+#define		B43_DMA64_TXPARITYDISABLE		0x00000800
 #define		B43_DMA64_TXADDREXT_MASK		0x00030000
 #define		B43_DMA64_TXADDREXT_SHIFT		16
 #define B43_DMA64_TXINDEX				0x04
@@ -111,6 +114,7 @@ struct b43_dmadesc32 {
 #define		B43_DMA64_RXFROFF_MASK		0x000000FE
 #define		B43_DMA64_RXFROFF_SHIFT		1
 #define		B43_DMA64_RXDIRECTFIFO		0x00000100
+#define		B43_DMA64_RXPARITYDISABLE		0x00000800
 #define		B43_DMA64_RXADDREXT_MASK		0x00030000
 #define		B43_DMA64_RXADDREXT_SHIFT		16
 #define B43_DMA64_RXINDEX				0x24
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -1136,6 +1136,41 @@ void b43_power_saving_ctl_bits(struct b4
 	}
 }
 
+#ifdef CONFIG_B43_BCMA
+static void b43_bcma_phy_reset(struct b43_wldev *dev)
+{
+	u32 flags;
+
+	/* Put PHY into reset */
+	flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+	flags |= B43_BCMA_IOCTL_PHY_RESET;
+	flags |= B43_BCMA_IOCTL_PHY_BW_20MHZ; /* Make 20 MHz def */
+	bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags);
+	udelay(2);
+
+	/* Take PHY out of reset */
+	flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+	flags &= ~B43_BCMA_IOCTL_PHY_RESET;
+	flags |= BCMA_IOCTL_FGC;
+	bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags);
+	udelay(1);
+
+	/* Do not force clock anymore */
+	flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+	flags &= ~BCMA_IOCTL_FGC;
+	bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags);
+	udelay(1);
+}
+
+static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode)
+{
+	b43_device_enable(dev, B43_BCMA_IOCTL_PHY_CLKEN);
+	bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST);
+	b43_bcma_phy_reset(dev);
+	bcma_core_pll_ctl(dev->dev->bdev, 0x300, 0x3000000, true);
+}
+#endif
+
 static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, bool gmode)
 {
 	struct ssb_device *sdev = dev->dev->sdev;
@@ -1168,7 +1203,18 @@ void b43_wireless_core_reset(struct b43_
 {
 	u32 macctl;
 
-	b43_ssb_wireless_core_reset(dev, gmode);
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		b43_bcma_wireless_core_reset(dev, gmode);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		b43_ssb_wireless_core_reset(dev, gmode);
+		break;
+#endif
+	}
 
 	/* Turn Analog ON, but only if we already know the PHY-type.
 	 * This protects against very early setup where we don't know the
@@ -1921,7 +1967,7 @@ static irqreturn_t b43_do_interrupt(stru
 		return IRQ_NONE;
 	reason &= dev->irq_mask;
 	if (!reason)
-		return IRQ_HANDLED;
+		return IRQ_NONE;
 
 	dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON)
 	    & 0x0001DC00;
@@ -2116,21 +2162,43 @@ static int b43_try_request_fw(struct b43
 	u32 tmshigh;
 	int err;
 
+	/* Files for HT and LCN were found by trying one by one */
+
 	/* Get microcode */
-	if ((rev >= 5) && (rev <= 10))
+	if ((rev >= 5) && (rev <= 10)) {
 		filename = "ucode5";
-	else if ((rev >= 11) && (rev <= 12))
+	} else if ((rev >= 11) && (rev <= 12)) {
 		filename = "ucode11";
-	else if (rev == 13)
+	} else if (rev == 13) {
 		filename = "ucode13";
-	else if (rev == 14)
+	} else if (rev == 14) {
 		filename = "ucode14";
-	else if (rev == 15)
+	} else if (rev == 15) {
 		filename = "ucode15";
-	else if ((rev >= 16) && (rev <= 20))
-		filename = "ucode16_mimo";
-	else
-		goto err_no_ucode;
+	} else {
+		switch (dev->phy.type) {
+		case B43_PHYTYPE_N:
+			if (rev >= 16)
+				filename = "ucode16_mimo";
+			else
+				goto err_no_ucode;
+			break;
+		case B43_PHYTYPE_HT:
+			if (rev == 29)
+				filename = "ucode29_mimo";
+			else
+				goto err_no_ucode;
+			break;
+		case B43_PHYTYPE_LCN:
+			if (rev == 24)
+				filename = "ucode24_mimo";
+			else
+				goto err_no_ucode;
+			break;
+		default:
+			goto err_no_ucode;
+		}
+	}
 	err = b43_do_request_fw(ctx, filename, &fw->ucode);
 	if (err)
 		goto err_load;
@@ -2189,6 +2257,18 @@ static int b43_try_request_fw(struct b43
 		else
 			goto err_no_initvals;
 		break;
+	case B43_PHYTYPE_HT:
+		if (rev == 29)
+			filename = "ht0initvals29";
+		else
+			goto err_no_initvals;
+		break;
+	case B43_PHYTYPE_LCN:
+		if (rev == 24)
+			filename = "lcn0initvals24";
+		else
+			goto err_no_initvals;
+		break;
 	default:
 		goto err_no_initvals;
 	}
@@ -2236,6 +2316,18 @@ static int b43_try_request_fw(struct b43
 		else
 			goto err_no_initvals;
 		break;
+	case B43_PHYTYPE_HT:
+		if (rev == 29)
+			filename = "ht0bsinitvals29";
+		else
+			goto err_no_initvals;
+		break;
+	case B43_PHYTYPE_LCN:
+		if (rev == 24)
+			filename = "lcn0bsinitvals24";
+		else
+			goto err_no_initvals;
+		break;
 	default:
 		goto err_no_initvals;
 	}
@@ -2607,11 +2699,24 @@ static int b43_gpio_init(struct b43_wlde
 	if (dev->dev->core_rev >= 2)
 		mask |= 0x0010;	/* FIXME: This is redundant. */
 
-	gpiodev = b43_ssb_gpio_dev(dev);
-	if (gpiodev)
-		ssb_write32(gpiodev, B43_GPIO_CONTROL,
-			    (ssb_read32(gpiodev, B43_GPIO_CONTROL)
-			     & mask) | set);
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,
+				(bcma_cc_read32(&dev->dev->bdev->bus->drv_cc,
+					BCMA_CC_GPIOCTL) & mask) | set);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		gpiodev = b43_ssb_gpio_dev(dev);
+		if (gpiodev)
+			ssb_write32(gpiodev, B43_GPIO_CONTROL,
+				    (ssb_read32(gpiodev, B43_GPIO_CONTROL)
+				    & mask) | set);
+		break;
+#endif
+	}
 
 	return 0;
 }
@@ -2621,9 +2726,21 @@ static void b43_gpio_cleanup(struct b43_
 {
 	struct ssb_device *gpiodev;
 
-	gpiodev = b43_ssb_gpio_dev(dev);
-	if (gpiodev)
-		ssb_write32(gpiodev, B43_GPIO_CONTROL, 0);
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,
+				0);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		gpiodev = b43_ssb_gpio_dev(dev);
+		if (gpiodev)
+			ssb_write32(gpiodev, B43_GPIO_CONTROL, 0);
+		break;
+#endif
+	}
 }
 
 /* http://bcm-specs.sipsolutions.net/EnableMac */
@@ -2695,12 +2812,30 @@ out:
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */
 void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on)
 {
-	u32 tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
-	if (on)
-		tmslow |= B43_TMSLOW_MACPHYCLKEN;
-	else
-		tmslow &= ~B43_TMSLOW_MACPHYCLKEN;
-	ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
+	u32 tmp;
+
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+		if (on)
+			tmp |= B43_BCMA_IOCTL_MACPHYCLKEN;
+		else
+			tmp &= ~B43_BCMA_IOCTL_MACPHYCLKEN;
+		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+		if (on)
+			tmp |= B43_TMSLOW_MACPHYCLKEN;
+		else
+			tmp &= ~B43_TMSLOW_MACPHYCLKEN;
+		ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+		break;
+#endif
+	}
 }
 
 static void b43_adjust_opmode(struct b43_wldev *dev)
@@ -2939,8 +3074,20 @@ static int b43_chip_init(struct b43_wlde
 
 	b43_mac_phy_clock_set(dev, true);
 
-	b43_write16(dev, B43_MMIO_POWERUP_DELAY,
-		    dev->sdev->bus->chipco.fast_pwrup_delay);
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		/* FIXME: 0xE74 is quite common, but should be read from CC */
+		b43_write16(dev, B43_MMIO_POWERUP_DELAY, 0xE74);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		b43_write16(dev, B43_MMIO_POWERUP_DELAY,
+			    dev->dev->sdev->bus->chipco.fast_pwrup_delay);
+		break;
+#endif
+	}
 
 	err = 0;
 	b43dbg(dev->wl, "Chip initialized\n");
@@ -3456,21 +3603,33 @@ static void b43_op_set_tsf(struct ieee80
 
 static void b43_put_phy_into_reset(struct b43_wldev *dev)
 {
-	struct ssb_device *sdev = dev->sdev;
-	u32 tmslow;
+	u32 tmp;
 
-	tmslow = ssb_read32(sdev, SSB_TMSLOW);
-	tmslow &= ~B43_TMSLOW_GMODE;
-	tmslow |= B43_TMSLOW_PHYRESET;
-	tmslow |= SSB_TMSLOW_FGC;
-	ssb_write32(sdev, SSB_TMSLOW, tmslow);
-	msleep(1);
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		b43err(dev->wl,
+		       "Putting PHY into reset not supported on BCMA\n");
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+		tmp &= ~B43_TMSLOW_GMODE;
+		tmp |= B43_TMSLOW_PHYRESET;
+		tmp |= SSB_TMSLOW_FGC;
+		ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+		msleep(1);
+
+		tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+		tmp &= ~SSB_TMSLOW_FGC;
+		tmp |= B43_TMSLOW_PHYRESET;
+		ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+		msleep(1);
 
-	tmslow = ssb_read32(sdev, SSB_TMSLOW);
-	tmslow &= ~SSB_TMSLOW_FGC;
-	tmslow |= B43_TMSLOW_PHYRESET;
-	ssb_write32(sdev, SSB_TMSLOW, tmslow);
-	msleep(1);
+		break;
+#endif
+	}
 }
 
 static const char *band_to_string(enum ieee80211_band band)
@@ -4100,6 +4259,12 @@ static int b43_phy_versioning(struct b43
 			unsupported = 1;
 		break;
 #endif
+#ifdef CONFIG_B43_PHY_LCN
+	case B43_PHYTYPE_LCN:
+		if (phy_rev > 1)
+			unsupported = 1;
+		break;
+#endif
 	default:
 		unsupported = 1;
 	};
@@ -4113,22 +4278,42 @@ static int b43_phy_versioning(struct b43
 	       analog_type, phy_type, phy_rev);
 
 	/* Get RADIO versioning */
-	if (dev->dev->chip_id == 0x4317) {
-		if (dev->dev->chip_rev == 0)
-			tmp = 0x3205017F;
-		else if (dev->dev->chip_rev == 1)
-			tmp = 0x4205017F;
-		else
-			tmp = 0x5205017F;
+	if (dev->dev->core_rev >= 24) {
+		u16 radio24[3];
+
+		for (tmp = 0; tmp < 3; tmp++) {
+			b43_write16(dev, B43_MMIO_RADIO24_CONTROL, tmp);
+			radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
+		}
+
+		/* Broadcom uses "id" for our "ver" and has separated "ver" */
+		/* radio_ver = (radio24[0] & 0xF0) >> 4; */
+
+		radio_manuf = 0x17F;
+		radio_ver = (radio24[2] << 8) | radio24[1];
+		radio_rev = (radio24[0] & 0xF);
 	} else {
-		b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
-		tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
-		b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
-		tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH) << 16;
-	}
-	radio_manuf = (tmp & 0x00000FFF);
-	radio_ver = (tmp & 0x0FFFF000) >> 12;
-	radio_rev = (tmp & 0xF0000000) >> 28;
+		if (dev->dev->chip_id == 0x4317) {
+			if (dev->dev->chip_rev == 0)
+				tmp = 0x3205017F;
+			else if (dev->dev->chip_rev == 1)
+				tmp = 0x4205017F;
+			else
+				tmp = 0x5205017F;
+		} else {
+			b43_write16(dev, B43_MMIO_RADIO_CONTROL,
+				    B43_RADIOCTL_ID);
+			tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
+			b43_write16(dev, B43_MMIO_RADIO_CONTROL,
+				    B43_RADIOCTL_ID);
+			tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH)
+				<< 16;
+		}
+		radio_manuf = (tmp & 0x00000FFF);
+		radio_ver = (tmp & 0x0FFFF000) >> 12;
+		radio_rev = (tmp & 0xF0000000) >> 28;
+	}
+
 	if (radio_manuf != 0x17F /* Broadcom */)
 		unsupported = 1;
 	switch (phy_type) {
@@ -4160,6 +4345,10 @@ static int b43_phy_versioning(struct b43
 		if (radio_ver != 0x2059)
 			unsupported = 1;
 		break;
+	case B43_PHYTYPE_LCN:
+		if (radio_ver != 0x2064)
+			unsupported = 1;
+		break;
 	default:
 		B43_WARN_ON(1);
 	}
@@ -4343,7 +4532,6 @@ static void b43_wireless_core_exit(struc
 /* Initialize a wireless core */
 static int b43_wireless_core_init(struct b43_wldev *dev)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
 	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 	struct b43_phy *phy = &dev->phy;
 	int err;
@@ -4362,7 +4550,20 @@ static int b43_wireless_core_init(struct
 	phy->ops->prepare_structs(dev);
 
 	/* Enable IRQ routing to this device. */
-	ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->sdev);
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci,
+				      dev->dev->bdev, true);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		ssb_pcicore_dev_irqvecs_enable(&dev->dev->sdev->bus->pcicore,
+					       dev->dev->sdev);
+		break;
+#endif
+	}
 
 	b43_imcfglo_timeouts_workaround(dev);
 	b43_bluetooth_coext_disable(dev);
@@ -4393,8 +4594,9 @@ static int b43_wireless_core_init(struct
 	if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
 		hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
 #ifdef CONFIG_SSB_DRIVER_PCICORE
-	if ((bus->bustype == SSB_BUSTYPE_PCI) &&
-	    (bus->pcicore.dev->id.revision <= 10))
+	if (dev->dev->bus_type == B43_BUS_SSB &&
+	    dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
+	    dev->dev->sdev->bus->pcicore.dev->id.revision <= 10)
 		hf |= B43_HF_PCISCW; /* PCI slow clock workaround. */
 #endif
 	hf &= ~B43_HF_SKCFPUP;
@@ -4764,9 +4966,9 @@ static void b43_wireless_core_detach(str
 static int b43_wireless_core_attach(struct b43_wldev *dev)
 {
 	struct b43_wl *wl = dev->wl;
-	struct ssb_bus *bus = dev->sdev->bus;
-	struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL;
+	struct pci_dev *pdev = NULL;
 	int err;
+	u32 tmp;
 	bool have_2ghz_phy = 0, have_5ghz_phy = 0;
 
 	/* Do NOT do any device initialization here.
@@ -4776,20 +4978,38 @@ static int b43_wireless_core_attach(stru
 	 * that in core_init(), too.
 	 */
 
+#ifdef CONFIG_B43_SSB
+	if (dev->dev->bus_type == B43_BUS_SSB &&
+	    dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI)
+		pdev = dev->dev->sdev->bus->host_pci;
+#endif
+
 	err = b43_bus_powerup(dev, 0);
 	if (err) {
 		b43err(wl, "Bus powerup failed\n");
 		goto out;
 	}
-	/* Get the PHY type. */
-	if (dev->dev->core_rev >= 5) {
-		u32 tmshigh;
 
-		tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH);
-		have_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY);
-		have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY);
-	} else
-		B43_WARN_ON(1);
+	/* Get the PHY type. */
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		tmp = bcma_aread32(dev->dev->bdev, BCMA_IOST);
+		have_2ghz_phy = !!(tmp & B43_BCMA_IOST_2G_PHY);
+		have_5ghz_phy = !!(tmp & B43_BCMA_IOST_5G_PHY);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		if (dev->dev->core_rev >= 5) {
+			tmp = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
+			have_2ghz_phy = !!(tmp & B43_TMSHIGH_HAVE_2GHZ_PHY);
+			have_5ghz_phy = !!(tmp & B43_TMSHIGH_HAVE_5GHZ_PHY);
+		} else
+			B43_WARN_ON(1);
+		break;
+#endif
+	}
 
 	dev->phy.gmode = have_2ghz_phy;
 	dev->phy.radio_on = 1;
@@ -4815,6 +5035,8 @@ static int b43_wireless_core_attach(stru
 #endif
 		case B43_PHYTYPE_G:
 		case B43_PHYTYPE_N:
+		case B43_PHYTYPE_HT:
+		case B43_PHYTYPE_LCN:
 			have_2ghz_phy = 1;
 			break;
 		default:
@@ -4877,13 +5099,13 @@ static void b43_one_core_detach(struct b
 	/* Do not cancel ieee80211-workqueue based work here.
 	 * See comment in b43_remove(). */
 
-	wldev = ssb_get_drvdata(dev->sdev);
+	wldev = b43_bus_get_wldev(dev);
 	wl = wldev->wl;
 	b43_debugfs_remove_device(wldev);
 	b43_wireless_core_detach(wldev);
 	list_del(&wldev->list);
 	wl->nr_devs--;
-	ssb_set_drvdata(dev->sdev, NULL);
+	b43_bus_set_wldev(dev, NULL);
 	kfree(wldev);
 }
 
@@ -4898,7 +5120,6 @@ static int b43_one_core_attach(struct b4
 
 	wldev->use_pio = b43_modparam_pio;
 	wldev->dev = dev;
-	wldev->sdev = dev->sdev; /* TODO: Remove when not needed */
 	wldev->wl = wl;
 	b43_set_status(wldev, B43_STAT_UNINIT);
 	wldev->bad_frames_preempt = modparam_bad_frames_preempt;
@@ -4910,7 +5131,7 @@ static int b43_one_core_attach(struct b4
 
 	list_add(&wldev->list, &wl->devlist);
 	wl->nr_devs++;
-	ssb_set_drvdata(dev->sdev, wldev);
+	b43_bus_set_wldev(dev, wldev);
 	b43_debugfs_add_device(wldev);
 
       out:
@@ -4959,11 +5180,12 @@ static void b43_wireless_exit(struct b43
 	ieee80211_free_hw(hw);
 }
 
-static struct b43_wl *b43_wireless_init(struct ssb_device *dev)
+static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
 {
-	struct ssb_sprom *sprom = &dev->bus->sprom;
+	struct ssb_sprom *sprom = dev->bus_sprom;
 	struct ieee80211_hw *hw;
 	struct b43_wl *wl;
+	char chip_name[6];
 
 	hw = ieee80211_alloc_hw(sizeof(*wl), &b43_hw_ops);
 	if (!hw) {
@@ -5002,21 +5224,70 @@ static struct b43_wl *b43_wireless_init(
 	INIT_WORK(&wl->tx_work, b43_tx_work);
 	skb_queue_head_init(&wl->tx_queue);
 
-	b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n",
-		dev->bus->chip_id, dev->id.revision);
+	snprintf(chip_name, ARRAY_SIZE(chip_name),
+		 (dev->chip_id > 0x9999) ? "%d" : "%04X", dev->chip_id);
+	b43info(wl, "Broadcom %s WLAN found (core revision %u)\n", chip_name,
+		dev->core_rev);
 	return wl;
 }
 
 #ifdef CONFIG_B43_BCMA
 static int b43_bcma_probe(struct bcma_device *core)
 {
-	b43err(NULL, "BCMA is not supported yet!");
-	return -EOPNOTSUPP;
+	struct b43_bus_dev *dev;
+	struct b43_wl *wl;
+	int err;
+
+	dev = b43_bus_dev_bcma_init(core);
+	if (!dev)
+		return -ENODEV;
+
+	wl = b43_wireless_init(dev);
+	if (IS_ERR(wl)) {
+		err = PTR_ERR(wl);
+		goto bcma_out;
+	}
+
+	err = b43_one_core_attach(dev, wl);
+	if (err)
+		goto bcma_err_wireless_exit;
+
+	err = ieee80211_register_hw(wl->hw);
+	if (err)
+		goto bcma_err_one_core_detach;
+	b43_leds_register(wl->current_dev);
+
+bcma_out:
+	return err;
+
+bcma_err_one_core_detach:
+	b43_one_core_detach(dev);
+bcma_err_wireless_exit:
+	ieee80211_free_hw(wl->hw);
+	return err;
 }
 
 static void b43_bcma_remove(struct bcma_device *core)
 {
-	/* TODO */
+	struct b43_wldev *wldev = bcma_get_drvdata(core);
+	struct b43_wl *wl = wldev->wl;
+
+	/* We must cancel any work here before unregistering from ieee80211,
+	 * as the ieee80211 unreg will destroy the workqueue. */
+	cancel_work_sync(&wldev->restart_work);
+
+	/* Restore the queues count before unregistering, because firmware detect
+	 * might have modified it. Restoring is important, so the networking
+	 * stack can properly free resources. */
+	wl->hw->queues = wl->mac80211_initially_registered_queues;
+	b43_leds_stop(wldev);
+	ieee80211_unregister_hw(wl->hw);
+
+	b43_one_core_detach(wldev->dev);
+
+	b43_leds_unregister(wl);
+
+	ieee80211_free_hw(wl->hw);
 }
 
 static struct bcma_driver b43_bcma_driver = {
@@ -5045,7 +5316,7 @@ int b43_ssb_probe(struct ssb_device *sde
 		/* Probing the first core. Must setup common struct b43_wl */
 		first = 1;
 		b43_sprom_fixup(sdev->bus);
-		wl = b43_wireless_init(sdev);
+		wl = b43_wireless_init(dev);
 		if (IS_ERR(wl)) {
 			err = PTR_ERR(wl);
 			goto out;
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -32,6 +32,7 @@
 #include "phy_n.h"
 #include "phy_lp.h"
 #include "phy_ht.h"
+#include "phy_lcn.h"
 #include "b43.h"
 #include "main.h"
 
@@ -65,6 +66,11 @@ int b43_phy_allocate(struct b43_wldev *d
 		phy->ops = &b43_phyops_ht;
 #endif
 		break;
+	case B43_PHYTYPE_LCN:
+#ifdef CONFIG_B43_PHY_LCN
+		phy->ops = &b43_phyops_lcn;
+#endif
+		break;
 	}
 	if (B43_WARN_ON(!phy->ops))
 		return -ENODEV;
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -198,6 +198,7 @@ struct b43_phy_g;
 struct b43_phy_n;
 struct b43_phy_lp;
 struct b43_phy_ht;
+struct b43_phy_lcn;
 
 struct b43_phy {
 	/* Hardware operation callbacks. */
@@ -222,6 +223,8 @@ struct b43_phy {
 		struct b43_phy_lp *lp;
 		/* HT-PHY specific information */
 		struct b43_phy_ht *ht;
+		/* LCN-PHY specific information */
+		struct b43_phy_lcn *lcn;
 	};
 
 	/* Band support flags. */
--- a/drivers/net/wireless/b43/phy_ht.c
+++ b/drivers/net/wireless/b43/phy_ht.c
@@ -24,9 +24,14 @@
 
 #include "b43.h"
 #include "phy_ht.h"
+#include "tables_phy_ht.h"
 #include "radio_2059.h"
 #include "main.h"
 
+/**************************************************
+ * Radio 2059.
+ **************************************************/
+
 static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
 			const struct b43_phy_ht_channeltab_e_radio2059 *e)
 {
@@ -56,7 +61,7 @@ static void b43_radio_2059_channel_setup
 	b43_radio_write(dev, 0x98, e->radio_syn98);
 
 	for (i = 0; i < 2; i++) {
-		routing = i ? 0x800 : 0x400;
+		routing = i ? R2059_RXRX1 : R2059_TXRX0;
 		b43_radio_write(dev, routing | 0x4a, e->radio_rxtx4a);
 		b43_radio_write(dev, routing | 0x58, e->radio_rxtx58);
 		b43_radio_write(dev, routing | 0x5a, e->radio_rxtx5a);
@@ -78,11 +83,120 @@ static void b43_radio_2059_channel_setup
 	udelay(300);
 }
 
+static void b43_radio_2059_init(struct b43_wldev *dev)
+{
+	const u16 routing[] = { R2059_SYN, R2059_TXRX0, R2059_RXRX1 };
+	const u16 radio_values[3][2] = {
+		{ 0x61, 0xE9 }, { 0x69, 0xD5 }, { 0x73, 0x99 },
+	};
+	u16 i, j;
+
+	b43_radio_write(dev, R2059_ALL | 0x51, 0x0070);
+	b43_radio_write(dev, R2059_ALL | 0x5a, 0x0003);
+
+	for (i = 0; i < ARRAY_SIZE(routing); i++)
+		b43_radio_set(dev, routing[i] | 0x146, 0x3);
+
+	b43_radio_set(dev, 0x2e, 0x0078);
+	b43_radio_set(dev, 0xc0, 0x0080);
+	msleep(2);
+	b43_radio_mask(dev, 0x2e, ~0x0078);
+	b43_radio_mask(dev, 0xc0, ~0x0080);
+
+	if (1) { /* FIXME */
+		b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x1);
+		udelay(10);
+		b43_radio_set(dev, R2059_RXRX1 | 0x0BF, 0x1);
+		b43_radio_maskset(dev, R2059_RXRX1 | 0x19B, 0x3, 0x2);
+
+		b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x2);
+		udelay(100);
+		b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x2);
+
+		for (i = 0; i < 10000; i++) {
+			if (b43_radio_read(dev, R2059_RXRX1 | 0x145) & 1) {
+				i = 0;
+				break;
+			}
+			udelay(100);
+		}
+		if (i)
+			b43err(dev->wl, "radio 0x945 timeout\n");
+
+		b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x1);
+		b43_radio_set(dev, 0xa, 0x60);
+
+		for (i = 0; i < 3; i++) {
+			b43_radio_write(dev, 0x17F, radio_values[i][0]);
+			b43_radio_write(dev, 0x13D, 0x6E);
+			b43_radio_write(dev, 0x13E, radio_values[i][1]);
+			b43_radio_write(dev, 0x13C, 0x55);
+
+			for (j = 0; j < 10000; j++) {
+				if (b43_radio_read(dev, 0x140) & 2) {
+					j = 0;
+					break;
+				}
+				udelay(500);
+			}
+			if (j)
+				b43err(dev->wl, "radio 0x140 timeout\n");
+
+			b43_radio_write(dev, 0x13C, 0x15);
+		}
+
+		b43_radio_mask(dev, 0x17F, ~0x1);
+	}
+
+	b43_radio_mask(dev, 0x11, ~0x0008);
+}
+
+/**************************************************
+ * Channel switching ops.
+ **************************************************/
+
 static void b43_phy_ht_channel_setup(struct b43_wldev *dev,
 				const struct b43_phy_ht_channeltab_e_phy *e,
 				struct ieee80211_channel *new_channel)
 {
-	/* TODO */
+	bool old_band_5ghz;
+	u8 i;
+
+	old_band_5ghz = b43_phy_read(dev, B43_PHY_HT_BANDCTL) & 0; /* FIXME */
+	if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
+		/* TODO */
+	} else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) {
+		/* TODO */
+	}
+
+	b43_phy_write(dev, B43_PHY_HT_BW1, e->bw1);
+	b43_phy_write(dev, B43_PHY_HT_BW2, e->bw2);
+	b43_phy_write(dev, B43_PHY_HT_BW3, e->bw3);
+	b43_phy_write(dev, B43_PHY_HT_BW4, e->bw4);
+	b43_phy_write(dev, B43_PHY_HT_BW5, e->bw5);
+	b43_phy_write(dev, B43_PHY_HT_BW6, e->bw6);
+
+	/* TODO: some ops on PHY regs 0x0B0 and 0xC0A */
+
+	/* TODO: separated function? */
+	for (i = 0; i < 3; i++) {
+		u16 mask;
+		u32 tmp = b43_httab_read(dev, B43_HTTAB32(26, 0xE8));
+
+		if (0) /* FIXME */
+			mask = 0x2 << (i * 4);
+		else
+			mask = 0;
+		b43_phy_mask(dev, B43_PHY_EXTG(0x108), mask);
+
+		b43_httab_write(dev, B43_HTTAB16(7, 0x110 + i), tmp >> 16);
+		b43_httab_write(dev, B43_HTTAB8(13, 0x63 + (i * 4)),
+				tmp & 0xFF);
+		b43_httab_write(dev, B43_HTTAB8(13, 0x73 + (i * 4)),
+				tmp & 0xFF);
+	}
+
+	b43_phy_write(dev, 0x017e, 0x3830);
 }
 
 static int b43_phy_ht_set_channel(struct b43_wldev *dev,
@@ -139,6 +253,13 @@ static void b43_phy_ht_op_prepare_struct
 	memset(phy_ht, 0, sizeof(*phy_ht));
 }
 
+static int b43_phy_ht_op_init(struct b43_wldev *dev)
+{
+	b43_phy_ht_tables_init(dev);
+
+	return 0;
+}
+
 static void b43_phy_ht_op_free(struct b43_wldev *dev)
 {
 	struct b43_phy *phy = &dev->phy;
@@ -155,13 +276,25 @@ static void b43_phy_ht_op_software_rfkil
 	if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
 		b43err(dev->wl, "MAC not suspended\n");
 
+	/* In the following PHY ops we copy wl's dummy behaviour.
+	 * TODO: Find out if reads (currently hidden in masks/masksets) are
+	 * needed and replace following ops with just writes or w&r.
+	 * Note: B43_PHY_HT_RF_CTL1 register is tricky, wrong operation can
+	 * cause delayed (!) machine lock up. */
 	if (blocked) {
-		b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, ~0);
+		b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, 0);
 	} else {
-		b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, ~0);
-		b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, ~0, 0x1);
-		b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, ~0);
-		b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, ~0, 0x2);
+		b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, 0);
+		b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, 0, 0x1);
+		b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, 0);
+		b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, 0, 0x2);
+
+		if (dev->phy.radio_ver == 0x2059)
+			b43_radio_2059_init(dev);
+		else
+			B43_WARN_ON(1);
+
+		b43_switch_channel(dev, dev->phy.channel);
 	}
 }
 
@@ -203,7 +336,7 @@ static int b43_phy_ht_op_switch_channel(
 static unsigned int b43_phy_ht_op_get_default_chan(struct b43_wldev *dev)
 {
 	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
-		return 1;
+		return 11;
 	return 36;
 }
 
@@ -247,6 +380,16 @@ static void b43_phy_ht_op_radio_write(st
 	b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
 }
 
+static enum b43_txpwr_result
+b43_phy_ht_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi)
+{
+	return B43_TXPWR_RES_DONE;
+}
+
+static void b43_phy_ht_op_adjust_txpower(struct b43_wldev *dev)
+{
+}
+
 /**************************************************
  * PHY ops struct.
  **************************************************/
@@ -255,9 +398,7 @@ const struct b43_phy_operations b43_phyo
 	.allocate		= b43_phy_ht_op_allocate,
 	.free			= b43_phy_ht_op_free,
 	.prepare_structs	= b43_phy_ht_op_prepare_structs,
-	/*
 	.init			= b43_phy_ht_op_init,
-	*/
 	.phy_read		= b43_phy_ht_op_read,
 	.phy_write		= b43_phy_ht_op_write,
 	.phy_maskset		= b43_phy_ht_op_maskset,
@@ -267,8 +408,6 @@ const struct b43_phy_operations b43_phyo
 	.switch_analog		= b43_phy_ht_op_switch_analog,
 	.switch_channel		= b43_phy_ht_op_switch_channel,
 	.get_default_chan	= b43_phy_ht_op_get_default_chan,
-	/*
 	.recalc_txpower		= b43_phy_ht_op_recalc_txpower,
 	.adjust_txpower		= b43_phy_ht_op_adjust_txpower,
-	*/
 };
--- a/drivers/net/wireless/b43/phy_ht.h
+++ b/drivers/net/wireless/b43/phy_ht.h
@@ -4,9 +4,16 @@
 #include "phy_common.h"
 
 
+#define B43_PHY_HT_BANDCTL			0x009 /* Band control */
 #define B43_PHY_HT_TABLE_ADDR			0x072 /* Table address */
 #define B43_PHY_HT_TABLE_DATALO			0x073 /* Table data low */
 #define B43_PHY_HT_TABLE_DATAHI			0x074 /* Table data high */
+#define B43_PHY_HT_BW1				0x1CE
+#define B43_PHY_HT_BW2				0x1CF
+#define B43_PHY_HT_BW3				0x1D0
+#define B43_PHY_HT_BW4				0x1D1
+#define B43_PHY_HT_BW5				0x1D2
+#define B43_PHY_HT_BW6				0x1D3
 
 #define B43_PHY_HT_RF_CTL1			B43_PHY_EXTG(0x010)
 
@@ -20,7 +27,12 @@
 
 /* Values for PHY registers used on channel switching */
 struct b43_phy_ht_channeltab_e_phy {
-	/* TODO */
+	u16 bw1;
+	u16 bw2;
+	u16 bw3;
+	u16 bw4;
+	u16 bw5;
+	u16 bw6;
 };
 
 
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_lcn.c
@@ -0,0 +1,52 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n LCN-PHY support
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/slab.h>
+
+#include "b43.h"
+#include "phy_lcn.h"
+#include "tables_phy_lcn.h"
+#include "main.h"
+
+/**************************************************
+ * PHY ops struct.
+ **************************************************/
+
+const struct b43_phy_operations b43_phyops_lcn = {
+	/*
+	.allocate		= b43_phy_lcn_op_allocate,
+	.free			= b43_phy_lcn_op_free,
+	.prepare_structs	= b43_phy_lcn_op_prepare_structs,
+	.init			= b43_phy_lcn_op_init,
+	.phy_read		= b43_phy_lcn_op_read,
+	.phy_write		= b43_phy_lcn_op_write,
+	.phy_maskset		= b43_phy_lcn_op_maskset,
+	.radio_read		= b43_phy_lcn_op_radio_read,
+	.radio_write		= b43_phy_lcn_op_radio_write,
+	.software_rfkill	= b43_phy_lcn_op_software_rfkill,
+	.switch_analog		= b43_phy_lcn_op_switch_analog,
+	.switch_channel		= b43_phy_lcn_op_switch_channel,
+	.get_default_chan	= b43_phy_lcn_op_get_default_chan,
+	.recalc_txpower		= b43_phy_lcn_op_recalc_txpower,
+	.adjust_txpower		= b43_phy_lcn_op_adjust_txpower,
+	*/
+};
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_lcn.h
@@ -0,0 +1,14 @@
+#ifndef B43_PHY_LCN_H_
+#define B43_PHY_LCN_H_
+
+#include "phy_common.h"
+
+
+struct b43_phy_lcn {
+};
+
+
+struct b43_phy_operations;
+extern const struct b43_phy_operations b43_phyops_lcn;
+
+#endif /* B43_PHY_LCN_H_ */
\ No newline at end of file
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -603,17 +603,33 @@ static void b43_nphy_tx_lp_fbw(struct b4
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
 static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force)
 {
-	u32 tmslow;
+	u32 tmp;
 
 	if (dev->phy.type != B43_PHYTYPE_N)
 		return;
 
-	tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
-	if (force)
-		tmslow |= SSB_TMSLOW_FGC;
-	else
-		tmslow &= ~SSB_TMSLOW_FGC;
-	ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+		if (force)
+			tmp |= BCMA_IOCTL_FGC;
+		else
+			tmp &= ~BCMA_IOCTL_FGC;
+		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+		if (force)
+			tmp |= SSB_TMSLOW_FGC;
+		else
+			tmp &= ~SSB_TMSLOW_FGC;
+		ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+		break;
+#endif
+	}
 }
 
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
@@ -958,8 +974,21 @@ static void b43_nphy_superswitch_init(st
 		b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0);
 		b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0);
 
-		ssb_chipco_gpio_control(&dev->sdev->bus->chipco, 0xFC00,
-					0xFC00);
+		switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+		case B43_BUS_BCMA:
+			bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc,
+						 0xFC00, 0xFC00);
+			break;
+#endif
+#ifdef CONFIG_B43_SSB
+		case B43_BUS_SSB:
+			ssb_chipco_gpio_control(&dev->dev->sdev->bus->chipco,
+						0xFC00, 0xFC00);
+			break;
+#endif
+		}
+
 		b43_write32(dev, B43_MMIO_MACCTL,
 			b43_read32(dev, B43_MMIO_MACCTL) &
 			~B43_MACCTL_GPOUTSMSK);
@@ -3600,7 +3629,20 @@ int b43_phy_initn(struct b43_wldev *dev)
 	if ((dev->phy.rev >= 3) &&
 	   (sprom->boardflags_lo & B43_BFL_EXTLNA) &&
 	   (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) {
-		chipco_set32(&dev->sdev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40);
+		switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+		case B43_BUS_BCMA:
+			bcma_cc_set32(&dev->dev->bdev->bus->drv_cc,
+				      BCMA_CC_CHIPCTL, 0x40);
+			break;
+#endif
+#ifdef CONFIG_B43_SSB
+		case B43_BUS_SSB:
+			chipco_set32(&dev->dev->sdev->bus->chipco,
+				     SSB_CHIPCO_CHIPCTL, 0x40);
+			break;
+#endif
+		}
 	}
 	nphy->deaf_count = 0;
 	b43_nphy_tables_init(dev);
--- a/drivers/net/wireless/b43/radio_2059.c
+++ b/drivers/net/wireless/b43/radio_2059.c
@@ -23,8 +23,152 @@
 #include "b43.h"
 #include "radio_2059.h"
 
+#define RADIOREGS(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
+		  r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
+		  r20, r21, r22, r23, r24, r25, r26, r27, r28) \
+	.radio_syn16			= r00,	\
+	.radio_syn17			= r01,	\
+	.radio_syn22			= r02,	\
+	.radio_syn25			= r03,	\
+	.radio_syn27			= r04,	\
+	.radio_syn28			= r05,	\
+	.radio_syn29			= r06,	\
+	.radio_syn2c			= r07,	\
+	.radio_syn2d			= r08,	\
+	.radio_syn37			= r09,	\
+	.radio_syn41			= r10,	\
+	.radio_syn43			= r11,	\
+	.radio_syn47			= r12,	\
+	.radio_syn4a			= r13,	\
+	.radio_syn58			= r14,	\
+	.radio_syn5a			= r15,	\
+	.radio_syn6a			= r16,	\
+	.radio_syn6d			= r17,	\
+	.radio_syn6e			= r18,	\
+	.radio_syn92			= r19,	\
+	.radio_syn98			= r20,	\
+	.radio_rxtx4a			= r21,	\
+	.radio_rxtx58			= r22,	\
+	.radio_rxtx5a			= r23,	\
+	.radio_rxtx6a			= r24,	\
+	.radio_rxtx6d			= r25,	\
+	.radio_rxtx6e			= r26,	\
+	.radio_rxtx92			= r27,	\
+	.radio_rxtx98			= r28
+
+#define PHYREGS(r0, r1, r2, r3, r4, r5)	\
+	.phy_regs.bw1	= r0,	\
+	.phy_regs.bw2	= r1,	\
+	.phy_regs.bw3	= r2,	\
+	.phy_regs.bw4	= r3,	\
+	.phy_regs.bw5	= r4,	\
+	.phy_regs.bw6	= r5
+
+static const struct b43_phy_ht_channeltab_e_radio2059 b43_phy_ht_channeltab_radio2059[] = {
+  {	.freq			= 2412,
+	RADIOREGS(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
+		  0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+  },
+  {	.freq			= 2417,
+	RADIOREGS(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
+		  0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+  },
+  {	.freq			= 2422,
+	RADIOREGS(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
+		  0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+  },
+  {	.freq			= 2427,
+	RADIOREGS(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
+		  0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+  },
+  {	.freq			= 2432,
+	RADIOREGS(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
+		  0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+  },
+  {	.freq			= 2437,
+	RADIOREGS(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
+		  0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+  },
+  {	.freq			= 2442,
+	RADIOREGS(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
+		  0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+  },
+  {	.freq			= 2447,
+	RADIOREGS(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
+		  0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+  },
+  {	.freq			= 2452,
+	RADIOREGS(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
+		  0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+  },
+  {	.freq			= 2457,
+	RADIOREGS(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
+		  0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+  },
+  {	.freq			= 2462,
+	RADIOREGS(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
+		  0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+  },
+  {	.freq			= 2467,
+	RADIOREGS(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3,
+		  0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+  },
+  {	.freq			= 2472,
+	RADIOREGS(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8,
+		  0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+  },
+};
+
 const struct b43_phy_ht_channeltab_e_radio2059
 *b43_phy_ht_get_channeltab_e_r2059(struct b43_wldev *dev, u16 freq)
 {
+	const struct b43_phy_ht_channeltab_e_radio2059 *e;
+	unsigned int i;
+
+	e = b43_phy_ht_channeltab_radio2059;
+	for (i = 0; i < ARRAY_SIZE(b43_phy_ht_channeltab_radio2059); i++, e++) {
+		if (e->freq == freq)
+			return e;
+	}
+
 	return NULL;
 }
--- a/drivers/net/wireless/b43/radio_2059.h
+++ b/drivers/net/wireless/b43/radio_2059.h
@@ -5,6 +5,11 @@
 
 #include "phy_ht.h"
 
+#define R2059_SYN			0x000
+#define R2059_TXRX0			0x400
+#define R2059_RXRX1			0x800
+#define R2059_ALL			0xC00
+
 /* Values for various registers uploaded on channel switching */
 struct b43_phy_ht_channeltab_e_radio2059 {
 	/* The channel frequency in MHz */
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_phy_ht.c
@@ -0,0 +1,750 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n HT-PHY data tables
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "tables_phy_ht.h"
+#include "phy_common.h"
+#include "phy_ht.h"
+
+static const u16 b43_httab_0x12[] = {
+	0x0000, 0x0008, 0x000a, 0x0010, 0x0012, 0x0019,
+	0x001a, 0x001c, 0x0080, 0x0088, 0x008a, 0x0090,
+	0x0092, 0x0099, 0x009a, 0x009c, 0x0100, 0x0108,
+	0x010a, 0x0110, 0x0112, 0x0119, 0x011a, 0x011c,
+	0x0180, 0x0188, 0x018a, 0x0190, 0x0192, 0x0199,
+	0x019a, 0x019c, 0x0000, 0x0098, 0x00a0, 0x00a8,
+	0x009a, 0x00a2, 0x00aa, 0x0120, 0x0128, 0x0128,
+	0x0130, 0x0138, 0x0138, 0x0140, 0x0122, 0x012a,
+	0x012a, 0x0132, 0x013a, 0x013a, 0x0142, 0x01a8,
+	0x01b0, 0x01b8, 0x01b0, 0x01b8, 0x01c0, 0x01c8,
+	0x01c0, 0x01c8, 0x01d0, 0x01d0, 0x01d8, 0x01aa,
+	0x01b2, 0x01ba, 0x01b2, 0x01ba, 0x01c2, 0x01ca,
+	0x01c2, 0x01ca, 0x01d2, 0x01d2, 0x01da, 0x0001,
+	0x0002, 0x0004, 0x0009, 0x000c, 0x0011, 0x0014,
+	0x0018, 0x0020, 0x0021, 0x0022, 0x0024, 0x0081,
+	0x0082, 0x0084, 0x0089, 0x008c, 0x0091, 0x0094,
+	0x0098, 0x00a0, 0x00a1, 0x00a2, 0x00a4, 0x0007,
+	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007,
+};
+
+static const u16 b43_httab_0x27[] = {
+	0x0009, 0x000e, 0x0011, 0x0014, 0x0017, 0x001a,
+	0x001d, 0x0020, 0x0009, 0x000e, 0x0011, 0x0014,
+	0x0017, 0x001a, 0x001d, 0x0020, 0x0009, 0x000e,
+	0x0011, 0x0014, 0x0017, 0x001a, 0x001d, 0x0020,
+	0x0009, 0x000e, 0x0011, 0x0014, 0x0017, 0x001a,
+	0x001d, 0x0020,
+};
+
+static const u16 b43_httab_0x26[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000,
+};
+
+static const u32 b43_httab_0x25[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_httab_0x2f[] = {
+	0x00035700, 0x0002cc9a, 0x00026666, 0x0001581f,
+	0x0001581f, 0x0001581f, 0x0001581f, 0x0001581f,
+	0x0001581f, 0x0001581f, 0x0001581f, 0x00035700,
+	0x0002cc9a, 0x00026666, 0x0001581f, 0x0001581f,
+	0x0001581f, 0x0001581f, 0x0001581f, 0x0001581f,
+	0x0001581f, 0x0001581f,
+};
+
+static const u16 b43_httab_0x1a[] = {
+	0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052,
+	0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e,
+	0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a,
+	0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046,
+	0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040,
+	0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a,
+	0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033,
+	0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b,
+	0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f,
+	0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e,
+	0x000b, 0x0007, 0x0002, 0x00fd,
+};
+
+static const u16 b43_httab_0x1b[] = {
+	0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052,
+	0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e,
+	0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a,
+	0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046,
+	0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040,
+	0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a,
+	0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033,
+	0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b,
+	0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f,
+	0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e,
+	0x000b, 0x0007, 0x0002, 0x00fd,
+};
+
+static const u16 b43_httab_0x1c[] = {
+	0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052,
+	0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e,
+	0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a,
+	0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046,
+	0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040,
+	0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a,
+	0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033,
+	0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b,
+	0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f,
+	0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e,
+	0x000b, 0x0007, 0x0002, 0x00fd,
+};
+
+static const u32 b43_httab_0x1a_0xc0[] = {
+	0x5bf70044, 0x5bf70042, 0x5bf70040, 0x5bf7003e,
+	0x5bf7003c, 0x5bf7003b, 0x5bf70039, 0x5bf70037,
+	0x5bf70036, 0x5bf70034, 0x5bf70033, 0x5bf70031,
+	0x5bf70030, 0x5ba70044, 0x5ba70042, 0x5ba70040,
+	0x5ba7003e, 0x5ba7003c, 0x5ba7003b, 0x5ba70039,
+	0x5ba70037, 0x5ba70036, 0x5ba70034, 0x5ba70033,
+	0x5b770044, 0x5b770042, 0x5b770040, 0x5b77003e,
+	0x5b77003c, 0x5b77003b, 0x5b770039, 0x5b770037,
+	0x5b770036, 0x5b770034, 0x5b770033, 0x5b770031,
+	0x5b770030, 0x5b77002f, 0x5b77002d, 0x5b77002c,
+	0x5b470044, 0x5b470042, 0x5b470040, 0x5b47003e,
+	0x5b47003c, 0x5b47003b, 0x5b470039, 0x5b470037,
+	0x5b470036, 0x5b470034, 0x5b470033, 0x5b470031,
+	0x5b470030, 0x5b47002f, 0x5b47002d, 0x5b47002c,
+	0x5b47002b, 0x5b47002a, 0x5b270044, 0x5b270042,
+	0x5b270040, 0x5b27003e, 0x5b27003c, 0x5b27003b,
+	0x5b270039, 0x5b270037, 0x5b270036, 0x5b270034,
+	0x5b270033, 0x5b270031, 0x5b270030, 0x5b27002f,
+	0x5b170044, 0x5b170042, 0x5b170040, 0x5b17003e,
+	0x5b17003c, 0x5b17003b, 0x5b170039, 0x5b170037,
+	0x5b170036, 0x5b170034, 0x5b170033, 0x5b170031,
+	0x5b170030, 0x5b17002f, 0x5b17002d, 0x5b17002c,
+	0x5b17002b, 0x5b17002a, 0x5b170028, 0x5b170027,
+	0x5b170026, 0x5b170025, 0x5b170024, 0x5b170023,
+	0x5b070044, 0x5b070042, 0x5b070040, 0x5b07003e,
+	0x5b07003c, 0x5b07003b, 0x5b070039, 0x5b070037,
+	0x5b070036, 0x5b070034, 0x5b070033, 0x5b070031,
+	0x5b070030, 0x5b07002f, 0x5b07002d, 0x5b07002c,
+	0x5b07002b, 0x5b07002a, 0x5b070028, 0x5b070027,
+	0x5b070026, 0x5b070025, 0x5b070024, 0x5b070023,
+	0x5b070022, 0x5b070021, 0x5b070020, 0x5b07001f,
+	0x5b07001e, 0x5b07001d, 0x5b07001d, 0x5b07001c,
+};
+
+static const u32 b43_httab_0x1a_0x140[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_httab_0x1b_0x140[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_httab_0x1c_0x140[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u16 b43_httab_0x1a_0x1c0[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000,
+};
+
+static const u16 b43_httab_0x1b_0x1c0[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000,
+};
+
+static const u16 b43_httab_0x1c_0x1c0[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000,
+};
+
+static const u16 b43_httab_0x1a_0x240[] = {
+	0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+	0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+	0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+	0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+	0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+	0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+	0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e,
+	0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+	0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+	0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc,
+	0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+	0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6,
+};
+
+static const u16 b43_httab_0x1b_0x240[] = {
+	0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+	0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+	0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+	0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+	0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+	0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+	0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e,
+	0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+	0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+	0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc,
+	0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+	0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6,
+};
+
+static const u16 b43_httab_0x1c_0x240[] = {
+	0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+	0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+	0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+	0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+	0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+	0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+	0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e,
+	0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+	0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+	0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc,
+	0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+	0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6,
+};
+
+static const u32 b43_httab_0x1f[] = {
+	0x00000000, 0x00000000, 0x00016023, 0x00006028,
+	0x00034036, 0x0003402e, 0x0007203c, 0x0006e037,
+	0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d,
+	0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9,
+	0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9,
+	0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6,
+	0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c,
+	0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b,
+	0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15,
+	0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9,
+	0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87,
+	0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3,
+	0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa,
+	0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff,
+	0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff,
+	0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff,
+};
+
+static const u32 b43_httab_0x21[] = {
+	0x00000000, 0x00000000, 0x00016023, 0x00006028,
+	0x00034036, 0x0003402e, 0x0007203c, 0x0006e037,
+	0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d,
+	0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9,
+	0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9,
+	0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6,
+	0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c,
+	0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b,
+	0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15,
+	0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9,
+	0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87,
+	0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3,
+	0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa,
+	0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff,
+	0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff,
+	0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff,
+};
+
+static const u32 b43_httab_0x23[] = {
+	0x00000000, 0x00000000, 0x00016023, 0x00006028,
+	0x00034036, 0x0003402e, 0x0007203c, 0x0006e037,
+	0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d,
+	0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9,
+	0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9,
+	0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6,
+	0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c,
+	0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b,
+	0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15,
+	0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9,
+	0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87,
+	0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3,
+	0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa,
+	0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff,
+	0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff,
+	0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff,
+};
+
+static const u32 b43_httab_0x20[] = {
+	0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035,
+	0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043,
+	0x07340047, 0x06d2004b, 0x067a004f, 0x06170054,
+	0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a,
+	0x04910070, 0x044c0077, 0x040f007e, 0x03d90085,
+	0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8,
+	0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3,
+	0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a,
+	0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e,
+	0x01720162, 0x015d0177, 0x0149018e, 0x013701a5,
+	0x012601be, 0x011501d8, 0x010601f4, 0x00f70212,
+	0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b,
+	0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348,
+	0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422,
+	0x00750460, 0x006e04a3, 0x006804e9, 0x00620533,
+	0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
+};
+
+static const u32 b43_httab_0x22[] = {
+	0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035,
+	0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043,
+	0x07340047, 0x06d2004b, 0x067a004f, 0x06170054,
+	0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a,
+	0x04910070, 0x044c0077, 0x040f007e, 0x03d90085,
+	0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8,
+	0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3,
+	0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a,
+	0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e,
+	0x01720162, 0x015d0177, 0x0149018e, 0x013701a5,
+	0x012601be, 0x011501d8, 0x010601f4, 0x00f70212,
+	0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b,
+	0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348,
+	0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422,
+	0x00750460, 0x006e04a3, 0x006804e9, 0x00620533,
+	0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
+};
+
+static const u32 b43_httab_0x24[] = {
+	0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035,
+	0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043,
+	0x07340047, 0x06d2004b, 0x067a004f, 0x06170054,
+	0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a,
+	0x04910070, 0x044c0077, 0x040f007e, 0x03d90085,
+	0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8,
+	0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3,
+	0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a,
+	0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e,
+	0x01720162, 0x015d0177, 0x0149018e, 0x013701a5,
+	0x012601be, 0x011501d8, 0x010601f4, 0x00f70212,
+	0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b,
+	0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348,
+	0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422,
+	0x00750460, 0x006e04a3, 0x006804e9, 0x00620533,
+	0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
+};
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+u32 b43_httab_read(struct b43_wldev *dev, u32 offset)
+{
+	u32 type, value;
+
+	type = offset & B43_HTTAB_TYPEMASK;
+	offset &= ~B43_HTTAB_TYPEMASK;
+	B43_WARN_ON(offset > 0xFFFF);
+
+	switch (type) {
+	case B43_HTTAB_8BIT:
+		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+		value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO) & 0xFF;
+		break;
+	case B43_HTTAB_16BIT:
+		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+		value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
+		break;
+	case B43_HTTAB_32BIT:
+		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+		value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATAHI);
+		value <<= 16;
+		value |= b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
+		break;
+	default:
+		B43_WARN_ON(1);
+		value = 0;
+	}
+
+	return value;
+}
+
+void b43_httab_read_bulk(struct b43_wldev *dev, u32 offset,
+			 unsigned int nr_elements, void *_data)
+{
+	u32 type;
+	u8 *data = _data;
+	unsigned int i;
+
+	type = offset & B43_HTTAB_TYPEMASK;
+	offset &= ~B43_HTTAB_TYPEMASK;
+	B43_WARN_ON(offset > 0xFFFF);
+
+	b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+
+	for (i = 0; i < nr_elements; i++) {
+		switch (type) {
+		case B43_HTTAB_8BIT:
+			*data = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO) & 0xFF;
+			data++;
+			break;
+		case B43_HTTAB_16BIT:
+			*((u16 *)data) = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
+			data += 2;
+			break;
+		case B43_HTTAB_32BIT:
+			*((u32 *)data) = b43_phy_read(dev, B43_PHY_HT_TABLE_DATAHI);
+			*((u32 *)data) <<= 16;
+			*((u32 *)data) |= b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
+			data += 4;
+			break;
+		default:
+			B43_WARN_ON(1);
+		}
+	}
+}
+
+void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value)
+{
+	u32 type;
+
+	type = offset & B43_HTTAB_TYPEMASK;
+	offset &= 0xFFFF;
+
+	switch (type) {
+	case B43_HTTAB_8BIT:
+		B43_WARN_ON(value & ~0xFF);
+		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+		b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
+		break;
+	case B43_HTTAB_16BIT:
+		B43_WARN_ON(value & ~0xFFFF);
+		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+		b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
+		break;
+	case B43_HTTAB_32BIT:
+		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+		b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, value >> 16);
+		b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value & 0xFFFF);
+		break;
+	default:
+		B43_WARN_ON(1);
+	}
+
+	return;
+}
+
+void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,
+			  unsigned int nr_elements, const void *_data)
+{
+	u32 type, value;
+	const u8 *data = _data;
+	unsigned int i;
+
+	type = offset & B43_HTTAB_TYPEMASK;
+	offset &= ~B43_HTTAB_TYPEMASK;
+	B43_WARN_ON(offset > 0xFFFF);
+
+	b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+
+	for (i = 0; i < nr_elements; i++) {
+		switch (type) {
+		case B43_HTTAB_8BIT:
+			value = *data;
+			data++;
+			B43_WARN_ON(value & ~0xFF);
+			b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
+			break;
+		case B43_HTTAB_16BIT:
+			value = *((u16 *)data);
+			data += 2;
+			B43_WARN_ON(value & ~0xFFFF);
+			b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
+			break;
+		case B43_HTTAB_32BIT:
+			value = *((u32 *)data);
+			data += 4;
+			b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, value >> 16);
+			b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO,
+					value & 0xFFFF);
+			break;
+		default:
+			B43_WARN_ON(1);
+		}
+	}
+}
+
+/**************************************************
+ * Tables ops.
+ **************************************************/
+
+#define httab_upload(dev, offset, data) do { \
+		b43_httab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
+	} while (0)
+void b43_phy_ht_tables_init(struct b43_wldev *dev)
+{
+	httab_upload(dev, B43_HTTAB16(0x12, 0), b43_httab_0x12);
+	httab_upload(dev, B43_HTTAB16(0x27, 0), b43_httab_0x27);
+	httab_upload(dev, B43_HTTAB16(0x26, 0), b43_httab_0x26);
+	httab_upload(dev, B43_HTTAB32(0x25, 0), b43_httab_0x25);
+	httab_upload(dev, B43_HTTAB32(0x2f, 0), b43_httab_0x2f);
+	httab_upload(dev, B43_HTTAB16(0x1a, 0), b43_httab_0x1a);
+	httab_upload(dev, B43_HTTAB16(0x1b, 0), b43_httab_0x1b);
+	httab_upload(dev, B43_HTTAB16(0x1c, 0), b43_httab_0x1c);
+	httab_upload(dev, B43_HTTAB32(0x1a, 0x0c0), b43_httab_0x1a_0xc0);
+	httab_upload(dev, B43_HTTAB32(0x1a, 0x140), b43_httab_0x1a_0x140);
+	httab_upload(dev, B43_HTTAB32(0x1b, 0x140), b43_httab_0x1b_0x140);
+	httab_upload(dev, B43_HTTAB32(0x1c, 0x140), b43_httab_0x1c_0x140);
+	httab_upload(dev, B43_HTTAB16(0x1a, 0x1c0), b43_httab_0x1a_0x1c0);
+	httab_upload(dev, B43_HTTAB16(0x1b, 0x1c0), b43_httab_0x1b_0x1c0);
+	httab_upload(dev, B43_HTTAB16(0x1c, 0x1c0), b43_httab_0x1c_0x1c0);
+	httab_upload(dev, B43_HTTAB16(0x1a, 0x240), b43_httab_0x1a_0x240);
+	httab_upload(dev, B43_HTTAB16(0x1b, 0x240), b43_httab_0x1b_0x240);
+	httab_upload(dev, B43_HTTAB16(0x1c, 0x240), b43_httab_0x1c_0x240);
+	httab_upload(dev, B43_HTTAB32(0x1f, 0), b43_httab_0x1f);
+	httab_upload(dev, B43_HTTAB32(0x21, 0), b43_httab_0x21);
+	httab_upload(dev, B43_HTTAB32(0x23, 0), b43_httab_0x23);
+	httab_upload(dev, B43_HTTAB32(0x20, 0), b43_httab_0x20);
+	httab_upload(dev, B43_HTTAB32(0x22, 0), b43_httab_0x22);
+	httab_upload(dev, B43_HTTAB32(0x24, 0), b43_httab_0x24);
+}
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_phy_ht.h
@@ -0,0 +1,22 @@
+#ifndef B43_TABLES_PHY_HT_H_
+#define B43_TABLES_PHY_HT_H_
+
+/* The HT-PHY tables. */
+#define B43_HTTAB_TYPEMASK		0xF0000000
+#define B43_HTTAB_8BIT			0x10000000
+#define B43_HTTAB_16BIT			0x20000000
+#define B43_HTTAB_32BIT			0x30000000
+#define B43_HTTAB8(table, offset)	(((table) << 10) | (offset) | B43_HTTAB_8BIT)
+#define B43_HTTAB16(table, offset)	(((table) << 10) | (offset) | B43_HTTAB_16BIT)
+#define B43_HTTAB32(table, offset)	(((table) << 10) | (offset) | B43_HTTAB_32BIT)
+
+u32 b43_httab_read(struct b43_wldev *dev, u32 offset);
+void b43_httab_read_bulk(struct b43_wldev *dev, u32 offset,
+			 unsigned int nr_elements, void *_data);
+void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value);
+void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,
+			  unsigned int nr_elements, const void *_data);
+
+void b43_phy_ht_tables_init(struct b43_wldev *dev);
+
+#endif /* B43_TABLES_PHY_HT_H_ */
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_phy_lcn.c
@@ -0,0 +1,34 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n LCN-PHY data tables
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "tables_phy_lcn.h"
+#include "phy_common.h"
+#include "phy_lcn.h"
+
+/**************************************************
+ * Tables ops.
+ **************************************************/
+
+void b43_phy_lcn_tables_init(struct b43_wldev *dev)
+{
+}
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_phy_lcn.h
@@ -0,0 +1,6 @@
+#ifndef B43_TABLES_PHY_LCN_H_
+#define B43_TABLES_PHY_LCN_H_
+
+void b43_phy_lcn_tables_init(struct b43_wldev *dev);
+
+#endif /* B43_TABLES_PHY_LCN_H_ */