mca80211: add support for b43 on bcma bus.
authorHauke Mehrtens <hauke@hauke-m.de>
Sat, 23 Jul 2011 11:25:05 +0000 (11:25 +0000)
committerHauke Mehrtens <hauke@hauke-m.de>
Sat, 23 Jul 2011 11:25:05 +0000 (11:25 +0000)
This makes b43 work on broadcom SoCs using bcma as system bus.

SVN-Revision: 27734

package/mac80211/Makefile
package/mac80211/patches/40-fix-compile-on-2-6-30.patch [new file with mode: 0644]
package/mac80211/patches/820-b43-backport.patch [new file with mode: 0644]
package/mac80211/patches/830-b43-read-correct-register-on-bcma-bus.patch [new file with mode: 0644]
package/mac80211/patches/840-b43-bus_fix_memory_corruption_when_setting_drivers.patch [new file with mode: 0644]
package/mac80211/patches/850-b43-add-core-rev-17-used-on-bcma-SoC.patch [new file with mode: 0644]

index 5270413c8a6ddbff3f13a79dfd5007b1101a8693..07af5f29d34103d05bab3296c9cde9c2e85a19b1 100644 (file)
@@ -852,6 +852,7 @@ endef
 
 define KernelPackage/b43
 $(call KernelPackage/b43-common)
+  DEPENDS+= +@DRIVER_11N_SUPPORT +!TARGET_brcm47xx:kmod-bcma
   TITLE:=Broadcom 43xx wireless support
   FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/b43/b43.ko
   AUTOLOAD:=$(call AutoLoad,30,b43)
@@ -864,7 +865,7 @@ define KernelPackage/b43/config
 
        choice
                prompt "b43 firmware version"
-               default B43_FW_4_150
+               default B43_FW_5_10
                help
                  This option allows you to select the version of the b43 firmware.
 
@@ -922,8 +923,7 @@ define KernelPackage/b43/config
        config B43_FW_SQUASH_COREREVS
                string "Core revisions to include"
                depends on B43_FW_SQUASH
-               default "5,6,7,8,9,10,11,13,14,15,16" if PACKAGE_B43_PHY_N
-               default "5,6,7,8,9,10,13,14,15" if !PACKAGE_B43_PHY_N
+               default "5,6,7,8,9,10,11,13,14,15,16"
                help
                  This is a comma seperated list of core revision numbers.
 
@@ -936,8 +936,7 @@ define KernelPackage/b43/config
        config B43_FW_SQUASH_PHYTYPES
                string "PHY types to include"
                depends on B43_FW_SQUASH
-               default "G,LP,N" if PACKAGE_B43_PHY_N
-               default "G,LP" if !PACKAGE_B43_PHY_N
+               default "G,LP,N"
                help
                  This is a comma seperated list of PHY types:
                    A  => A-PHY
@@ -973,12 +972,30 @@ define KernelPackage/b43/config
        config PACKAGE_B43_PHY_N
                bool "Enable support for N-PHYs"
                select B43_FW_5_10
-               default n
+               default y
                help
                  Enable support for BCM4321 and BCM4322.
 
                  Currently only 11g speed is available.
 
+                 If unsure, say Y.
+
+       config PACKAGE_B43_PHY_HT
+               bool "Enable support for HT-PHYs"
+               select B43_FW_5_10
+               default n
+               help
+                 Currently borken.
+
+                 If unsure, say N.
+
+       config PACKAGE_B43_PHY_LCN
+               bool "Enable support for LCN-PHYs"
+               select B43_FW_5_10
+               default n
+               help
+                 Currently borken.
+
                  If unsure, say N.
 
        endmenu
@@ -1045,7 +1062,12 @@ BUILDFLAGS:= \
        $(if $(CONFIG_ATH_USER_REGD),-DATH_USER_REGD=1) \
        $(if $(CONFIG_PACKAGE_B43_DEBUG),-DCONFIG_B43_DEBUG) \
        $(if $(CONFIG_PACKAGE_B43_PIO),-DCONFIG_B43_PIO) \
+       $(if $(CONFIG_PACKAGE_B43_PIO),-DCONFIG_B43_BCMA_PIO) \
        $(if $(CONFIG_PACKAGE_B43_PHY_N),-DCONFIG_B43_PHY_N) \
+       $(if $(CONFIG_PACKAGE_B43_PHY_HT),-DCONFIG_B43_PHY_HT) \
+       $(if $(CONFIG_PACKAGE_B43_PHY_LCN),-DCONFIG_B43_PHY_LCN) \
+       -DCONFIG_B43_BCMA \
+       -DCONFIG_B43_SSB \
        $(if $(CONFIG_PACKAGE_RT2X00_LIB_DEBUGFS),-DCONFIG_RT2X00_LIB_DEBUGFS) \
        $(if $(CONFIG_PACKAGE_RT2X00_DEBUG),-DCONFIG_RT2X00_DEBUG) \
        $(if $(NEED_RT2X00_LIB_HT),-DCONFIG_RT2X00_LIB_HT) \
@@ -1081,7 +1103,12 @@ MAKE_OPTS:= \
        CONFIG_B43LEGACY=$(if $(CONFIG_PACKAGE_kmod-b43legacy),m) \
        CONFIG_B43_DEBUG=$(if $(CONFIG_PACKAGE_B43_DEBUG),y) \
        CONFIG_B43_PIO=$(if $(CONFIG_PACKAGE_B43_PIO),y) \
+       CONFIG_B43_BCMA_PIO=$(if $(CONFIG_PACKAGE_B43_PIO),y) \
        CONFIG_B43_PHY_N=$(if $(CONFIG_PACKAGE_B43_PHY_N),y) \
+       CONFIG_B43_PHY_HT=$(if $(CONFIG_PACKAGE_B43_PHY_HT),y) \
+       CONFIG_B43_PHY_LCN=$(if $(CONFIG_PACKAGE_B43_PHY_LCN),y) \
+       CONFIG_B43_BCMA=y \
+       CONFIG_B43_SSB=y \
        CONFIG_ATH_COMMON=$(if $(CONFIG_PACKAGE_kmod-ath),m) \
        CONFIG_ATH_DEBUG=$(if $(CONFIG_PACKAGE_ATH_DEBUG),y) \
        CONFIG_ATH9K_PKTLOG=$(if $(CONFIG_PACKAGE_ATH_DEBUG),y) \
@@ -1199,6 +1226,7 @@ define Build/Prepare
        $(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(ZD1211FW_NAME)-$(ZD1211FW_VERSION).tar.bz2
        $(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(PKG_LINUX_FIRMWARE_SOURCE)
        rm -rf $(PKG_BUILD_DIR)/include/linux/ssb
+       rm -rf $(PKG_BUILD_DIR)/include/linux/bcma
        rm -f $(PKG_BUILD_DIR)/include/net/ieee80211.h
 endef
 
diff --git a/package/mac80211/patches/40-fix-compile-on-2-6-30.patch b/package/mac80211/patches/40-fix-compile-on-2-6-30.patch
new file mode 100644 (file)
index 0000000..2773585
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/b43/main.c~ 2011-07-23 00:33:46.573306410 +0200
++++ b/drivers/net/wireless/b43/main.c  2011-07-23 00:36:14.657726075 +0200
+@@ -4955,7 +4955,7 @@
+ static void b43_wireless_core_detach(struct b43_wldev *dev)
+ {
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
+-      if (dev->sdev->bus->bustype != SSB_BUSTYPE_SDIO)
++      if (dev->dev->sdev->bus->bustype != SSB_BUSTYPE_SDIO)
+               compat_destroy_threaded_irq(&dev->irq_compat);
+ #endif
+       /* We release firmware that late to not be required to re-request
diff --git a/package/mac80211/patches/820-b43-backport.patch b/package/mac80211/patches/820-b43-backport.patch
new file mode 100644 (file)
index 0000000..ec3b144
--- /dev/null
@@ -0,0 +1,2568 @@
+--- 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_ */
diff --git a/package/mac80211/patches/830-b43-read-correct-register-on-bcma-bus.patch b/package/mac80211/patches/830-b43-read-correct-register-on-bcma-bus.patch
new file mode 100644 (file)
index 0000000..8d88a66
--- /dev/null
@@ -0,0 +1,40 @@
+From f706821596d8a3dcda314c38b13d91f108fdc435 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Fri, 22 Jul 2011 17:10:29 +0200
+Subject: [PATCH 21/22] b43: read correct register on bcma bus.
+
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ drivers/net/wireless/b43/dma.c |   20 +++++++++++++++++---
+ 1 files changed, 17 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/b43/dma.c
++++ b/drivers/net/wireless/b43/dma.c
+@@ -795,9 +795,23 @@ static u64 supported_dma_mask(struct b43
+       u32 tmp;
+       u16 mmio_base;
+-      tmp = b43_read32(dev, SSB_TMSHIGH);
+-      if (tmp & SSB_TMSHIGH_DMA64)
+-              return DMA_BIT_MASK(64);
++      switch (dev->dev->bus_type) {
++#ifdef CONFIG_B43_BCMA
++      case B43_BUS_BCMA:
++              tmp = bcma_aread32(dev->dev->bdev, BCMA_IOST);
++              if (tmp & BCMA_IOST_DMA64)
++                      return DMA_BIT_MASK(64);
++              break;
++#endif
++#ifdef CONFIG_B43_SSB
++      case B43_BUS_SSB:
++              tmp = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
++              if (tmp & SSB_TMSHIGH_DMA64)
++                      return DMA_BIT_MASK(64);
++              break;
++#endif
++      }
++
+       mmio_base = b43_dmacontroller_base(0, 0);
+       b43_write32(dev, mmio_base + B43_DMA32_TXCTL, B43_DMA32_TXADDREXT_MASK);
+       tmp = b43_read32(dev, mmio_base + B43_DMA32_TXCTL);
diff --git a/package/mac80211/patches/840-b43-bus_fix_memory_corruption_when_setting_drivers.patch b/package/mac80211/patches/840-b43-bus_fix_memory_corruption_when_setting_drivers.patch
new file mode 100644 (file)
index 0000000..a325ada
--- /dev/null
@@ -0,0 +1,26 @@
+Fixes bug described in:
+https://bugzilla.kernel.org/show_bug.cgi?id=39172
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+John: this is trivial and fixes quite ugly memory (linked list exactly)
+corruption. I believe this fix should be taken for 3.1.
+---
+ drivers/net/wireless/b43/bus.c |    2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
+
+--- a/drivers/net/wireless/b43/bus.c
++++ b/drivers/net/wireless/b43/bus.c
+@@ -244,10 +244,12 @@ void b43_bus_set_wldev(struct b43_bus_de
+ #ifdef CONFIG_B43_BCMA
+       case B43_BUS_BCMA:
+               bcma_set_drvdata(dev->bdev, wldev);
++              break;
+ #endif
+ #ifdef CONFIG_B43_SSB
+       case B43_BUS_SSB:
+               ssb_set_drvdata(dev->sdev, wldev);
++              break;
+ #endif
+       }
+ }
diff --git a/package/mac80211/patches/850-b43-add-core-rev-17-used-on-bcma-SoC.patch b/package/mac80211/patches/850-b43-add-core-rev-17-used-on-bcma-SoC.patch
new file mode 100644 (file)
index 0000000..24a38b5
--- /dev/null
@@ -0,0 +1,21 @@
+From 46c79b0cdc60a974da409d641a69086694046ea0 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Fri, 22 Jul 2011 17:47:46 +0200
+Subject: [PATCH 23/23] b43: add core rev 17 used on bcma SoC
+
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ drivers/net/wireless/b43/main.c |    1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -120,6 +120,7 @@ MODULE_PARM_DESC(pio, "Use PIO accesses
+ #ifdef CONFIG_B43_BCMA
+ static const struct bcma_device_id b43_bcma_tbl[] = {
++      BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS),
+       BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS),
+       BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
+       BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS),